Firebase-tools: Adicione o emulador de autenticação Firebase ao pacote de emuladores

Criado em 26 set. 2019  ·  66Comentários  ·  Fonte: firebase/firebase-tools

É possível emular a API de autenticação para um desenvolvimento local mais rápido e testes completos? Com o emulador Firestore, não precisamos criar projetos diferentes para ambientes diferentes (dev, testing, staging, prod), podemos apenas usar o emulador, gerar dados de arquivos JSON no modo de observação para desenvolvimento ou propagação para cada caso de teste, etc. Para ser capaz de escrever um teste de ponta a ponta que tenha um login de usuário, navegação baseada na função e, em seguida, alguma ação, temos que criar um projeto separado para isolar usuários de teste e também propagar e limpar usuários lá para cada caso de teste.

emulator-suite feature request

Comentários muito úteis

Estamos trabalhando arduamente em um emulador de autenticação completa, que esperamos ser o que
todo mundo quer. Não posso oferecer nenhum cronograma no momento, mas é de alta prioridade
para nós.

Na sexta-feira, 22 de maio de 2020 às 8h12, ChuckB [email protected] escreveu:

@samtstern https://github.com/samtstern Qualquer progresso ou outro
solução para este problema / recurso? Eu preciso de (1) setEmulatedUser para trabalhar com o
o emulador Firestore de nuvem para que eu possa fazer testes manuais localmente.

Por seu comentário: em 17 de outubro de 2019
_Acho que claramente (2) é a história certa, mas eu estava tentando ter uma noção de
quantas pessoas ficariam felizes com (1), pois é substancialmente mais simples de
implementar e manter.

(1) Faça login para usar serviços como Firestore ou Realtime Database sem
realmente criando usuários reais. Agora é algo como
setEmulatedUser resolveria. Isso apenas permitiria que você tivesse uma autenticação falsa
token localmente que os emuladores aceitariam, mas seria rejeitado por
prod. Mais segurança, mais isolamento, etc._

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/firebase/firebase-tools/issues/1677#issuecomment-632660684 ,
ou cancelar
https://github.com/notifications/unsubscribe-auth/ACATB2Q4LV7NXMQFEALNPXLRSZT25ANCNFSM4I27PTFA
.

Todos 66 comentários

@vladimirdjurdjevic obrigado por levantar isso! Isso está em nossa lista de coisas a fazer, mas ainda não decidimos quanto do serviço de autenticação devemos emular e a melhor estratégia para fazê-lo. Certas coisas (como autenticação anônima) são muito fáceis de emular, enquanto outras (como autenticação por SMS) são muito difíceis.

Mas definitivamente queremos habilitar o caso de uso de ponta a ponta que você mencionou!

Pergunta: você acharia útil se houvesse uma biblioteca que permitisse simular localmente um usuário do Firebase para uso com os emuladores? Algo como:

firebase.auth().setEmulatedUser({
   uid: 'abc123',
   // ...
});

@samtstern A chamada para setEmulatedUser() também acionaria quaisquer functions.auth.user().onCreate() funções de nuvem emuladas? Nesse caso, isso seria muito útil.

@samtstern Isso ajudaria em alguns cenários de teste com certeza, mas ainda requer uma instância real para o desenvolvimento. Minha ideia é evitar a criação de vários projetos Firebase para ambientes diferentes e ser capaz de desenvolver localmente (talvez offline). Outra abordagem seria oferecer suporte a diferentes ambientes para serviços. Se pudéssemos criar ambientes diferentes para, digamos, firestore e auth no mesmo projeto, isso resolveria muitos problemas. Eu sei que posso criar projetos por ambiente, mas isso é um verdadeiro pé no saco. Configurando todos os ambientes, replicando dados, etc. Idealmente, gostaria de poder criar um projeto Firebase e, se precisar de dados fictícios para testes manuais, poderia apenas criar um ambiente de teste para o Firestore e fazer upload dos dados lá.

@noelmansour boa pergunta! Isso não seria muito difícil de fazer, provavelmente desejaríamos duas chamadas diferentes, como signInAsEmulatedUser e signUpAsEmulatedUser onde apenas a segunda aciona a função.

@vladimirdjurdjevic concorda totalmente que um emulador completo é melhor. Você poderia explicar o que você precisa de uma "instância real para desenvolvimento" que não são resolvidas por ser capaz de definir o usuário localmente?

Pergunta: você acharia útil se houvesse uma biblioteca que permitisse simular localmente um usuário do Firebase para uso com os emuladores?

Muito útil, ajudaria muito.
No momento, estou apenas configurando para true a função de regra que valida o usuário logado toda vez que tenho que testar algo localmente. É muito inseguro, mas provavelmente a coisa mais simples que posso fazer sem emular o usuário atual.

Sim, isso seria incrivelmente útil

Eu também gostaria de fazer o teste de unidade functions.auth.user().onCreate() . Suponho que agora a melhor solução alternativa seja, essencialmente, exportar a função de retorno de chamada passada para onCreate e fornecer um objeto user falso a ela.

Para esse tipo de teste de unidade, verifique o firebase-functions-test
biblioteca, que ajuda a invocar seus manipuladores de função com dados fictícios.

No domingo, 13 de outubro de 2019, 5:44, Daniel K. [email protected] escreveu:

Eu também gostaria de testar a unidade functions.auth.user (). OnCreate (). eu
suponha que agora a melhor solução alternativa seja exportar o retorno de chamada
função passada onCreate e fornecer um objeto de usuário falso a ela.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/firebase/firebase-tools/issues/1677?email_source=notifications&email_token=ACATB2QYJLX2LNVDTWJV25TQOMJ4VA5CNFSM4I27PTFKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEBCVQIQ#issuecomment-541415458 ,
ou cancelar
https://github.com/notifications/unsubscribe-auth/ACATB2SO3IR6UB73F4EMZPTQOMJ4VANCNFSM4I27PTFA
.

@samtstern Isso realmente funciona junto com o emulador Firestore? Com base nisso, tenho a impressão de que é para um propósito diferente.

image
https://firebase.google.com/docs/functions/unit-testing#initializing

Eu certamente não quero o modo online para testes de unidade, isso seria um slowpoke. E não tenho certeza se posso acessar o emulador Firestore por "stub".

@FredyC obrigado por apontar esses documentos. As palavras usadas são confusas porque os "modos" não são uma opção que você pode habilitar, eles apenas descrevem estratégias que você pode tomar.

Se você iniciasse o emulador Firestore junto com seus testes de unidade, seu código definitivamente poderia se conectar a ele. Se você definir a variável de ambiente FIRESTORE_EMULATOR_HOST , o SDK Admin do Firebase se conectará automaticamente ao emulador do Firestore ( firebase emulators:exec faz isso por você).

@samtstern Ainda tenho problemas para conectar os pontos e como tudo isso vai me ajudar a testar functions.auth.user().onCreate() ? Quero dizer, é ótimo que as funções se conectem ao emulador em vez de uma versão de produção, mas isso é apenas Firestore, certo? Como invoco a criação do usuário a partir de testes para realmente ter o código de função para iniciar?

Parece haver algum método enigmático makeUserRecord no firebase-functions-test mencionado, mas não faz muito sentido como isso funcionaria ou como realmente usá-lo.

Tentei chamar auth.createUserWithEmailAndPassword() do pacote @firebase/testing , mas isso está reclamando de chave API inválida, então presumo que funcionaria apenas com a versão online.

Quando eu procuro em org para aquela variável env que você mencionou, ela está apenas em três lugares e nenhum parece ser realmente relevante para auth. A menos que esteja oculto por alguma concatenação de string.

Também tenho navegado por https://github.com/firebase/functions-samples, mas não encontrei nenhum exemplo de teste de unidade lá.

Você pode entender isso? :)

Eu também tenho outro caso, um tanto oposto, em que o código da função de nuvem está usando a chamada admin.auth().getUserByEmail() . Surpreendentemente, não termina com o erro, mas não tenho ideia de como criaria esse usuário para que ele possa ser retornado. Exceto, é claro, zombar de todo o módulo de administração, mas isso é loucura :)

@samtstern Desculpe pela demora. Quando digo instância real, quero dizer instância real: D Idealmente, eu só quero trocar a configuração em meu arquivo de ambiente angular para desenvolvimento e continuar implementando recursos de autenticação como se meu aplicativo estivesse se comunicando com uma API real, mas ele realmente emulador rodando no meu máquina, e posso fazê-lo offline. Agora, eu entendo os desafios de enviar SMS, por exemplo. Seria bobagem esperar que o emulador enviasse SMS reais para o meu telefone, mas talvez você pudesse apenas imprimi-lo no console (o conteúdo do SMS que seria enviado). Provavelmente é mais incômodo do que o valor com isso. É por isso que acho que apenas o suporte a vários ambientes por projeto pode tornar as coisas muito melhores. Demora muito tempo para replicar configurações entre vários projetos para ambientes diferentes. E também gerenciar várias contas de serviço para scripts para poder propagar dados para diferentes projetos Firestore é uma dor. É por isso que ensinei que, se tivéssemos uma plataforma Firebase inteira emulada, poderíamos usá-la para todos os ambientes de não produção e gerenciar apenas um projeto Firebase real. Mas talvez apenas o suporte a vários ambientes por projeto seja uma solução melhor com um resultado aceitável.

@FredyC obrigado por todos os seus comentários! É muito útil para nós ver como isso pode ser confuso. Existem duas coisas principais que as pessoas desejam fazer em seus testes relacionados à autenticação:

  1. Faça login para usar serviços como Firestore ou Realtime Database sem realmente criar usuários reais. No momento, isso é o que algo como setEmulatedUser resolveria. Isso apenas permitiria que você tivesse um token de autenticação falso localmente que os emuladores aceitariam, mas seria rejeitado por prod. Mais segurança, mais isolamento, etc.
  2. Na verdade, teste a autenticação diretamente. Isso teria algumas peças:
    uma. Um emulador de autenticação que responde a todas as chamadas de API necessárias para que você possa apontar os SDKs do Auth para ele.
    b. Integração entre esse emulador e o emulador de funções para que .onCreate funções sejam acionadas corretamente.
    c. Simulação automática dentro do emulador de funções para que admin.auth() aponte para o emulador Auth, assim como fazemos para Firestore e RTDB hoje.

Acho que claramente (2) é a história certa, mas eu estava tentando ter uma ideia de quantas pessoas ficariam felizes com (1), uma vez que é substancialmente mais simples de implementar e manter.

@samtstern entendo. Corrija-me se eu estiver errado, mas (1) já não está resolvido? Quero dizer, em testes, posso apenas chamar o seguinte e o emulador Firestore me reconhecerá como esse usuário para que eu possa testar as regras de segurança. Na verdade, ainda não tentei, mas parece promissor até agora :)

  const app = firebase.initializeTestApp({
    projectId,
    auth: {
      uid: 'owner'
    }
  })

O (2) definitivamente parece muito útil, mas muito mais complexo de resolver. Infelizmente, minha visão do produto completo é tão limitada que não posso oferecer nenhuma ideia útil aqui.

Acho que deve ser construído de forma incremental. Em vez de tentar cobrir todos os cenários de uma vez, crie-o com base em casos de uso conhecidos e adicione-os em movimento. Na minha opinião limitada, emular "banco de dados do usuário" junto com acionadores de função não parece tão difícil de fazer.

@FredyC você está certo que (1) está resolvido para uso dentro de suítes de teste. Mas o outro caso de uso é, na verdade, conectar seu aplicativo Android / iOS / Web diretamente ao emulador para desenvolvimento local. Nesse caso, você não pode usar @firebase/testing .

Entendo. Honestamente, seria excelente se @firebase/testing pudesse ser usado em várias plataformas em vez de ter soluções separadas. Quero dizer, o quão difícil pode ser redirecionar a comunicação para o emulador? O FIRESTORE_EMULATOR_HOST exatamente isso? Embora eu ache que algo como FIREBASE_EMULATOR_HOST seria mais apropriado se o emulador também tivesse outros serviços.

@vladimirdjurdjevic Estou pensando, não funcionaria basicamente para simular o método signInWithPhone para que você possa controlar seu comportamento? Então você não precisa se preocupar com um emulador e obter código SMS simulado no console :)

Claro, então você precisa de alguma forma de autenticação em relação ao emulador para Firestore (e se conectar a ele). Algo como descrevi em https://github.com/firebase/firebase-tools/issues/1677#issuecomment -542897671 anterior. Existe um método subjacente para gerar tokens não seguros: https://github.com/firebase/firebase-js-sdk/blob/master/packages/testing/src/api/index.ts#L64. Não tenho certeza se isso funcionaria.

Claro, simular bibliotecas de terceiros nem sempre é tão fácil, mas uma vez descoberto, pode trazer ótimos resultados. Eventualmente, ele pode ser extraído para alguma biblioteca para torná-lo geralmente mais fácil.

Também estou pensando que esses métodos de signIn podem gerar uma grande quantidade de códigos de erro, algo que os testes adequados também devem cuidar. Isso também é fácil de fazer com a zombaria.

@samtstern Estender o contexto do namespace firebase.auth() com algo tópico como setEmulatedUser parece um antipadrão com as estratégias de emulação existentes. Essa recomendação talvez seja influenciada pela facilidade de extensibilidade no lado do pacote?

Em linha com os outros emuladores, eu esperaria que uma camada de serviço de autenticação separada fosse iniciada por HTTP e uma configuração do lado do cliente pudesse redirecionar a superfície API existente para utilizar.

Eu preferiria que os casos excêntricos do AuthN retornassem erros com a API Admin e Client dando suporte mínimo a CRUD para usuários básicos sobre nome de usuário / senha. Caramba, eu acho que mesmo começar com suporte a token personalizado no Admin e signInWithCustomToken iria realmente longe. Talvez implemente o que você precisa com uma matriz de suporte de API publicada nos documentos.

Para o ponto @FredyC , a estratégia atual para o teste de autenticação de integração é importar condicionalmente o @firebase/testing no código do aplicativo para rotear para a chamada initializeTestApp . Esta ação enfatiza a exclusão de pacote no momento da criação para as equipes de projeto e também espalha as configurações de redirecionamento do emulador entre duas APIs de pacote ( initializeTestApp e firestore.settings / functions.useFunctionsEmulator )

Hackeie o planeta!

a estratégia atual para o teste de autenticação de integração é importar condicionalmente o @firebase/testing no código do aplicativo para rotear para a chamada initializeTestApp .

Hum, estou chamando esse método dentro de testes. O truque é que initializeApp regular reside em index.ts que importa funções. Ele está sendo chamado quando o emulador é iniciado, mas quando os testes estão sendo executados, é um processo diferente e não entra em conflito um com o outro. Portanto, não há realmente nenhuma carga de importação condicional.

Claro, isso pode ser diferente para testar a autenticação, por exemplo. aplicativo da web em que o executor de teste compartilha o processo com o código do aplicativo. No entanto, com o teste de unidade, você geralmente não importa um aplicativo inteiro para um teste. O initializeApp provavelmente é feito em algum código que não é relevante para os testes e não é importado.

@FredyC concordou com os usos documentados para testes de unidade. Estava realmente falando sobre cenários de aplicativo completo em que as apis divergem e as importações dinâmicas saem do mapa documentado.

Eu só queria dar a você a atribuição de Honestly, it would be kinda superb if @firebase/testing could be used cross-platform instead of having separate solutions . digital high five

@FredyC obrigado por todos os seus comentários! É muito útil para nós ver como isso pode ser confuso. Existem duas coisas principais que as pessoas desejam fazer em seus testes relacionados à autenticação:

  1. Faça login para usar serviços como Firestore ou Realtime Database sem realmente criar usuários reais. No momento, isso é o que algo como setEmulatedUser resolveria. Isso apenas permitiria que você tivesse um token de autenticação falso localmente que os emuladores aceitariam, mas seria rejeitado por prod. Mais segurança, mais isolamento, etc.
  2. Na verdade, teste a autenticação diretamente. Isso teria algumas peças:
    uma. Um emulador de autenticação que responde a todas as chamadas de API necessárias para que você possa apontar os SDKs do Auth para ele.
    b. Integração entre esse emulador e o emulador de funções para que .onCreate funções sejam acionadas corretamente.
    c. Simulação automática dentro do emulador de funções para que admin.auth() aponte para o emulador Auth, assim como fazemos para Firestore e RTDB hoje.

Acho que claramente (2) é a história certa, mas eu estava tentando ter uma ideia de quantas pessoas ficariam felizes com (1), uma vez que é substancialmente mais simples de implementar e manter.

@samtstern antes de mais nada, gostaria de ter esse tipo de emulação.

Eu veria não. 1 muito útil para escrever testes e2e. Atualmente tenho que usar instância real para autenticação enquanto posso usar emulador para hospedagem, regras, firestore e funções.

Acho que deveria ser possível usar setEmulatedUser para simular o usuário da mesma forma que é feito em firebase.initializeTestApp. Deve ser possível enviar, por exemplo, tokens personalizados e outros dados relacionados ao usuário.

Também deve ser possível obter credenciais de amostra que podem ser usadas no aplicativo cliente com firebase.auth().signInWithCredential(credential)

Obrigado @vladimirdjurdjevic por trazer esse problema à tona! Já faz quase um ano que procurávamos uma solução.

Gostaríamos de ver um emulador real para três coisas:

  1. O e2e testa todo o aplicativo, então não precisamos criar ambientes diferentes, como disse @vladimirdjurdjevic .
  2. Testes de integração para o back-end, onde as APIs são chamadas e o usuário deve ser validado no Firebase.
  3. Todos os nossos desenvolvedores estão usando um ambiente Firebase central durante o desenvolvimento, o que causa muitas colisões. Claro, cada desenvolvedor pode criar seu próprio projeto Firebase, mas eles ainda precisam gerenciar seus usuários de teste no painel do Firebase, o que não é o ideal. Além disso, gostaríamos de desenvolver nosso aplicativo offline, o que não é possível hoje devido à falta de um emulador real.

Espero que você libere algo para nós em breve, isso tornaria seu produto mais valioso! A produtividade do desenvolvedor é muito importante nesses serviços!

Este parece ser um recurso na lista de desejos de muitas pessoas. O Firebase auth parece ser o IDaaS nº 1 agora em termos de preços, então é realmente uma dor que você não pode desenvolver localmente com ele com o Cloud Functions. Espero que a equipe do FB tenha novidades para nós em breve! 🙏

Edit: Pinging @mbleigh de @ firebase-ops já que esta discussão está enterrada em problemas ...

Também tenho este erro ... função ignorada porque o emulador de autenticação não existe ou não está em execução.

isso é acionado por este código:

functions.auth.user (). onDelete ()

qualquer informação sobre isso ...

@dominikfoldi

Eu concordo com seus pontos. Uma dica que pode ajudá-lo nesse ínterim:

Claro, cada desenvolvedor pode criar seu próprio projeto Firebase, mas eles ainda precisam gerenciar seus usuários de teste no painel do Firebase, o que não é o ideal.

Você pode propagar e gerenciar usuários programaticamente usando o SDK de administrador do Firebase, por exemplo, auth().createUser , consulte também https://firebase.google.com/docs/auth/admin/manage-users

Depois de ler este tópico, acho que as pessoas aqui podem achar o Foundry útil.

Sou um dos cofundadores da Foundry. Foundry é uma ferramenta CLI que pega seu Firebase Cloud Functions e cria uma cópia de seu aplicativo Firebase de produção em nossos servidores que atuam como seu ambiente de desenvolvimento no qual você executa diretamente seu código. Nenhuma configuração é necessária.

O Foundry observa seus arquivos de código-fonte e toda vez que você salva seu código localmente, nós o executamos em nossos servidores e devolvemos os resultados em apenas alguns segundos. Tudo é super rápido.
Você especifica quais dados Firestore, RealtimeDB e Auth Users devem ser copiados de seu aplicativo de produção por meio de nosso arquivo YAML para que você os tenha disponíveis durante o desenvolvimento.

 users:
      - getFromProd: 5 # Copy first 5 users from your Firebase project
      - getFromProd: ['id-1', 'id-2'] # Copy users with the specified IDs from your Firebase project

 # Copy first 3 documents from production from the collection 'userWorkspaces'
 # also add a custom document with id 'new-user-workspace' with a new data
 # format that you want to use
 firestore:
     - collection: userWorkspaces
       docs:
         - getFromProd: 3
         - id: new-user-workspace
           data: {"newDataFormat": 42}

Você também especifica como devemos acionar suas funções de nuvem quando executamos seu código. Funciona como um REPL para as funções da nuvem. Dessa forma, você sempre tem certeza de que suas funções de nuvem funcionarão corretamente com os dados de produção e no ambiente de produção depois de implantá-los.
Além disso, suas funções de nuvem agem como se tivessem sido implantadas.

Esses ambientes de desenvolvimento são criados ad-hoc assim que você inicia sua sessão. Portanto, todos em sua equipe operam em seu próprio ambiente, onde podem brincar.

Não quero enviar spam para a discussão aqui, então sinta-se à vontade para me enviar um e-mail com qualquer dúvida [email protected]
Estou mais do que feliz em ajudá-lo a configurar o Foundry em seus projetos, basta me enviar um e-mail!

Ainda assim, pelo que você descreveu e pelo que li na página inicial, esse serviço é baseado na nuvem.
Em vez disso, o emulador do Firebase funciona mesmo offline, daí sua utilidade para testes automáticos.

@samtstern Algum progresso ou outra solução para este problema / recurso? Eu preciso (1) setEmulatedUser para trabalhar com o emulador Firestore da nuvem para que eu possa fazer o teste manual localmente. Outra opção seria ter um argumento de linha de comando que define a id do usuário quando o emulador é iniciado. Desta forma, o emulador seria executado sob o ID do usuário passado durante a inicialização. Desta forma, as regras podem ser testadas localmente.

Por seu comentário: em 17 de outubro de 2019
_Acho que (2) é a história certa, mas estava tentando ter uma ideia de quantas pessoas ficariam felizes com (1), pois é substancialmente mais simples de implementar e manter.

(1) Faça login para usar serviços como Firestore ou Realtime Database sem realmente criar usuários reais. No momento, isso é o que algo como setEmulatedUser resolveria. Isso apenas permitiria que você tivesse um token de autenticação falso localmente que os emuladores aceitariam, mas seria rejeitado por prod. Mais segurança, mais isolamento, etc._

Estamos trabalhando arduamente em um emulador de autenticação completa, que esperamos ser o que
todo mundo quer. Não posso oferecer nenhum cronograma no momento, mas é de alta prioridade
para nós.

Na sexta-feira, 22 de maio de 2020 às 8h12, ChuckB [email protected] escreveu:

@samtstern https://github.com/samtstern Qualquer progresso ou outro
solução para este problema / recurso? Eu preciso de (1) setEmulatedUser para trabalhar com o
o emulador Firestore de nuvem para que eu possa fazer testes manuais localmente.

Por seu comentário: em 17 de outubro de 2019
_Acho que claramente (2) é a história certa, mas eu estava tentando ter uma noção de
quantas pessoas ficariam felizes com (1), pois é substancialmente mais simples de
implementar e manter.

(1) Faça login para usar serviços como Firestore ou Realtime Database sem
realmente criando usuários reais. Agora é algo como
setEmulatedUser resolveria. Isso apenas permitiria que você tivesse uma autenticação falsa
token localmente que os emuladores aceitariam, mas seria rejeitado por
prod. Mais segurança, mais isolamento, etc._

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/firebase/firebase-tools/issues/1677#issuecomment-632660684 ,
ou cancelar
https://github.com/notifications/unsubscribe-auth/ACATB2Q4LV7NXMQFEALNPXLRSZT25ANCNFSM4I27PTFA
.

1. Faça login para usar serviços como Firestore ou Realtime Database sem realmente criar usuários reais. No momento, isso é o que algo como setEmulatedUser resolveria. Isso apenas permitiria que você tivesse um token de autenticação falso localmente que os emuladores aceitariam, mas seria rejeitado por prod. Mais segurança, mais isolamento, etc.

Eu ficaria feliz com o número 1 aqui, nesse ínterim

@ rishisingh-dev, não é possível colocar um emulador de autenticação em execução porque os emuladores do Firebase atualmente não fornecem um.

Mas é perfeitamente possível testar funções de nuvem que envolvam autenticação nelas. Você pode refatorar a função que precisa de alguma API de autenticação e simular nos testes, enquanto fornece a função real no arquivo de funções do firebase. A fidelidade de sua configuração de teste é menor, mas então se torna uma questão de grau, não de tipo: você está apenas testando as chamadas de autenticação diretamente, mas pode testar o que espera que sejam.

Nessa pergunta SO seria algo como:

function sendWelcomeEmail(user) {
  console.log(user.uid);
  console.log(user.email);
  console.log(user.displayName);
}

exports.sendWelcomeEmail = functions.auth.user().onCreate((user) => sendWelcomeEmail(user));

E em seus testes você chama sendWelcomeEmail diretamente para garantir que ele faça o que você precisa.

Imagine que você tenha uma função de nuvem mais complicada chamada addFriend , onde o usuário insere um e-mail de amigo e você quer o uid. Você pode obter isso por meio de auths getUserByEmail .

function addFriend(email, getUserByEmail ) {
  const friendUid = getUserByEmail(email);
  // do things with friendUid;
}

exports.addFriend = functions.https.onCall(async (data, context) => {
  const email = data.email;
  const getUserByEmail = (email) => admin.auth().getUserByEmail(email);
  return { res: await addFriend(email, getUserByEmail ) };
}

Na declaração fn da nuvem, você envia getUserByEmail reais, mas em seus testes, você envia uma falsa:

async function testAddFriend() {
  const emails = {"[email protected]": "test-uid")
  const fakeGetUserByEmail = (email) => emails[email];
  addFriend("[email protected]);
  // verify the things were done with friendUid
}

Não acho que isso seja significativamente diferente do que testar qualquer API de terceiros em um teste de unidade. Ter os emuladores firebase fornecendo auth remove o boilerplate para cenários de teste de ponta a ponta, mas não altera significativamente os testes de unidade, já que você não gostaria que o estado persistente fosse mantido entre os testes de qualquer maneira.

Adoraria ser capaz de executar isso localmente sem ter que fazer upload para a nuvem para verificar

export const onCreate = functions.auth.user().onCreate((user) => {
    addGravatarURLtoUserData(user.uid, user.email)
})

export const addGravatarURLtoUserData = async (uid, email) => {
    const hash = crypto.createHash("md5").update(email).digest("hex")
    await admin.database().ref(`users/${uid}`).update({ gravatarURL: uid })
}

A propósito, posso obter user.displayName dentro da função onCreate?

sim, se estiver definido, eu acho, você experimentou?

Sim, ele retorna nulo.
Tentei na nuvem (não localmente).

Screen Shot 2020-07-10 at 2 43 12 AM

Meu código está aqui.

exports.sendWelcomeEmail = functions.auth.user().onCreate((user) => {
  console.log(user.uid);
  console.log(user.email);
  console.log(user.displayName);
});

Interessante bem, eu não uso o nome de exibição, eu uso o displayName de usuários personalizados para
banco de dados em tempo real

/**
 * updates Custom data in the realtime datastore users object, except for the username
 * <strong i="7">@param</strong> data
 * <strong i="8">@returns</strong> {Promise<void>}
 */
export async function updatePersonalData(data) {
    const { displayName } = data
    try {
        await firebase
            .database()
            .ref("users/" + firebase.auth().currentUser.uid)
            .update({
                displayName: displayName,
            })

        userDataStore.update((user) => {
            return { ...user, displayName: displayName }
        })
    } catch (e) {
        alert(e.message)
    }
}

Na sexta-feira, 10 de julho de 2020 às 10:44, rishisingh-dev [email protected]
escreveu:

Sim, ele retorna nulo.
Tentei na nuvem (não localmente).

[imagem: Screen Shot 2020-07-10 at 2 43 12 AM]
https://user-images.githubusercontent.com/56976320/87140958-29f3ac80-c257-11ea-98d3-084fad619de7.png

Meu código está aqui.

console.log (user.uid);
console.log (user.email);
console.log (user.displayName);
}); `` `

-
Você está recebendo isto porque está inscrito neste tópico.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/firebase/firebase-tools/issues/1677#issuecomment-656587759 ,
ou cancelar
https://github.com/notifications/unsubscribe-auth/AABU35Q27EMMHYAYU5CNZR3R23PIDANCNFSM4I27PTFA
.

>

Atenciosamente

Nikos Katsikanis

Sim, meu objetivo principal era atualizar o banco de dados com informações do usuário dentro da função onCreate .
Mas como não consigo obter displayName , criei uma função onCallable e a fiz.

Obrigado.

@samtstern Estou muito feliz em ver você trabalhando nisso :) Acabei de começar um novo projeto com o firebase, e a experiência de dev já é muito melhor (com a opção de emulador ui e --inspect-functions). Estou ansioso para ver o emulador de autenticação em ação :) Ótimo trabalho!

outra das melhores coisas é que não preciso abrir o Chrome sem segurança

@samtstern

Dois meses depois, é possível fazer uma estimativa aproximada?

Gostaríamos de enviar no início do próximo ano. Estamos agora diante da decisão de começar a escrever testes de integração em um projeto real ou se esperarmos alguns meses pelo emulador de autenticação. Você poderia nos ajudar um pouco aqui?

Melhor,

Niklas

Nossa política no Firebase não é dar estimativas de quando algo será lançado, a menos que tenhamos 100% de certeza. No momento, estamos trabalhando duro no emulador Auth, mas não estamos perto o suficiente para escolher uma data de lançamento.

É uma das nossas principais prioridades, mas acho que você não deve esperar que comecemos a testar seu aplicativo. Escreva seus testes no prod hoje, troque-os para direcionar o emulador quando estiver disponível.

Tudo bem, obrigado @samtstern. Isso ajuda!

Gostaríamos muito de usar um emulador de autenticação para testar as solicitações do Cloud Functions e do Firestore que envolvem declarações personalizadas em tokens de usuário. Podemos meio que testar declarações personalizadas com o Firestore no playground de regras no Firebase Console, mas um emulador de autenticação completo, teoricamente, nos permitiria fazer muito mais na forma de testes quando se trata de tokens de usuário.

Para ser claro: estamos comprometidos com um emulador de autenticação completo que emula os terminais de serviço reais (sempre que possível). Não estamos mais considerando algo leve como meus comentários anteriores sugeriram.

@samtstern isso é ótimo de ouvir (junto com as declarações personalizadas, uma vez que é frequentemente usado com integrações de terceiros). Existe algum lugar onde possamos acompanhar o progresso / ETA?

@fandy não, desculpe, não temos nada para compartilhar ainda ...

Obrigado Sam, atualmente estou fazendo todos os meus testes manualmente porque não é
vale o esforço para escrever testes e2e sem simulações de Auth

Na quarta-feira, 26 de agosto de 2020 às 14:32, Sam Stern [email protected] escreveu:

>
>

@fandy https://github.com/fandy não, desculpe, não temos nada para
compartilhe ainda ...

-
Você está recebendo isto porque está inscrito neste tópico.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/firebase/firebase-tools/issues/1677#issuecomment-680850282 ,
ou cancelar
https://github.com/notifications/unsubscribe-auth/AABU35UAQDBYEXKKINJSM43SCT6E7ANCNFSM4I27PTFA
.

-

Atenciosamente

Nikos Katsikanis

Para contornar isso, experimentei importar @ firebase / testing no navegador. Isso realmente não funcionou. Isso, no entanto, faz: mangle @ firebase / testing source para copiar o seguinte trecho ligeiramente editado:

import firebase from "firebase/app"
import * as component from "@firebase/component"
import * as util from "@firebase/util"
import { __awaiter, __generator } from "tslib"

function createUnsecuredJwt(auth) {
    // Unsecured JWTs use "none" as the algorithm.
    var header = {
        alg: 'none',
        kid: 'fakekid'
    };
    // Ensure that the auth payload has a value for 'iat'.
    auth.iat = auth.iat || 0;
    // Use `uid` field as a backup when `sub` is missing.
    auth.sub = auth.sub || auth.uid;
    if (!auth.sub) {
        throw new Error("auth must be an object with a 'sub' or 'uid' field");
    }
    // Unsecured JWTs use the empty string as a signature.
    var signature = '';
    return [
        util.base64.encodeString(JSON.stringify(header), /*webSafe=*/ false),
        util.base64.encodeString(JSON.stringify(auth), /*webSafe=*/ false),
        signature
    ].join('.');
}

function initializeApp(accessToken, options) {
    var _this = this;
    var app = firebase.initializeApp(options);
    if (accessToken) {
        var mockAuthComponent = new component.Component('auth-internal', function () {
            return ({
                getToken: function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
                    return [2 /*return*/, ({ accessToken: accessToken })];
                }); }); },
                getUid: function () { return null; },
                addAuthTokenListener: function (listener) {
                    // Call listener once immediately with predefined accessToken.
                    listener(accessToken);
                },
                removeAuthTokenListener: function () { }
            });
        }, "PRIVATE" /* PRIVATE */);
        app._addOrOverwriteComponent(mockAuthComponent);
    }
    return app;
}

export function initializeTestApp(options) {
  let accessToken = undefined
  if (options.auth !== undefined) {
    accessToken = createUnsecuredJwt(options.auth)
  }
  return initializeApp(accessToken, options)
}

Agora, no código do navegador do seu aplicativo, você pode importá-lo e

  let app
  if (dev) {
    app = initializeTestApp({projectId: "test", auth: {uid: "testuser"}})
    app.firestore().settings({
      host: "localhost:8080",
      ssl: false,
    })
  } else {
    app = firebaseProduction.initializeApp({ firebase config here })
    app.firestore().settings({ firestore config here })
  }
  window.firebase = app

Isso funciona muito bem! Agora, quando estou executando o desenvolvimento, tenho um falso usuário local que o emulador pensa ser "testuser" (como mostra o guia de teste de regras de segurança do firestore).

Outra solução alternativa que utilizo é fazer o stub da sua autenticação (estou usando usuários falsos gerados para testes).

Exemplo de TypeScript:

import type { User as AuthUser } from '@firebase/auth-types'
// not importing a type, but a module of types
import { auth as authTypes} from 'firebase/app'
type Auth = authTypes.Auth

export const authStub = {
    getUser(uid: string) {
        // for uids like `testuser1234uid`
        let n = uid ? uid.replace("testuser", '').replace("uid", '') : ''
        return Promise.resolve({
            uid,
            email: `test.user${n}@foo.com`,
            emailVerified: true,
            providerData: [{
                providerId: 'google.com',
                email: `test.user${n}@foo.com`,
                uid: `testuser${n}provideruid`,
                phoneNumber: null,
                displayName: `Test User ${n}`.trim(),
                photoURL: 'https://thispersondoesnotexist.com/image',
            }],
            metadata: {
                // https://firebase.google.com/docs/reference/admin/node/admin.auth.UserMetadata
                createTime: new Date().toUTCString(),
                lastSignInTime: new Date().toUTCString()
            },
            customClaims: {
                username: `testuser${n}`
            }
        })
    },
    deleteUser(uid: string) {
        return Promise.resolve()
    },
    async updateUser(uid: string, data: AuthUser) {
        let user = await this.getUser(uid)
        return { ...user, data }
    },
    setCustomUserClaims(uid: string, customUserClaims: Object): Promise<void> {
        return Promise.resolve()
    }
}

export const auth = <Auth><unknown>authStub

Também modifique suas regras, pois auth.token não é emulado. Por exemplo:

const rules = fs.readFileSync(__dirname + '/src/firebase/firestore/firestore.rules', 'utf8')
const modifiedRules =
    rules
        .replace(/request\.auth\.token\.email_verified/g, "true")
        .replace(/request\.auth\.token\.firebase\.sign_in_provider/g, "'password'")

await firebase.loadFirestoreRules({ projectId, rules: modifiedRules })

Está funcionando muito bem para mim. Espero que ajude…

Se você está seguindo esta discussão e deseja ser um testador Alpha do Firebase Authentication Emulator, siga estas etapas:

  1. Inscreva-se no programa Firebase Alpha: https://services.google.com/fb/forms/firebasealphaprogram/
  2. Envie-me um e-mail para [email protected] , certifique-se de enviá-lo do endereço de e-mail que você usará para o teste.

Faça isso apenas se estiver seriamente interessado em experimentar um emulador de estágio inicial e fornecer feedback! Haverá bugs e algumas partes da configuração serão difíceis, mas queremos saber o que você acha.

@samtstern Esta é uma ótima notícia! Eu adoraria experimentar, mas estarei produzindo meu projeto atual no final da semana, então não posso me dar ao luxo de tocá-lo no momento. Vou me inscrever no alpha assim que puder :) Obrigado pelo excelente trabalho.

100% vão querer tentar isso! você é o homem Sam!

@samtstern ansioso para experimentar e ajudar no que puder!

Preciso usar o recurso de autenticação para testar funções localmente do Android, o contexto de autenticação é sempre nulo

Boas notícias, o Authentication Emulator faz parte da nova versão 8.14.0 ! 🙌🎊

Obrigado pelo trabalho duro pessoal e @samtstern 💪

Rapazes incríveis!

Sou apenas o mensageiro! O emulador Auth foi 99% construído por @yuchenshi ... e é por isso que vou deixá-lo ter a honra de encerrar este problema quando acordar.

Existe alguma documentação sobre este novo emulador? (como instalar, configurar clientes, etc)

PSTObrigado por todo o trabalho duro nisso. Isso vai permitir todo tipo de coisa legal para nós.

@nicoburns muito em breve! Anúncio oficial, documentos e todas essas coisas boas em breve.

Boas notícias! :) Mal posso esperar para experimentar :)

Eu sei que você estava esperando por isso, então vamos direto ao ponto:

  • O emulador de autenticação Firebase já está disponível. Você pode obtê-lo instalando Firebase CLI> = v8.14.0.
  • Siga o guia do Emulator Suite para começar e conectar seus aplicativos .
  • Para anúncios empolgantes como este e muito mais, sintonize a transmissão ao vivo do Firebase Summit AGORA MESMO. **

** Plugue sem vergonha: eu também estou fazendo uma sessão sobre "Como configurar CI usando o pacote de emulador do Firebase" mais tarde hoje. Localizar isso na programação da sessão é deixado como um exercício para o leitor.


_P.S. Eu realmente não posso levar 99% do crédito, já que o Emulador Auth é, obviamente, um trabalho em equipe. Várias pessoas no Firebase e os desenvolvedores do Firebase (você) desempenharam um grande papel nisso também. Obrigado!_

@yuchenshi É possível exportar usuários criados na saída, assim como com o emulador Firestore?

@vdjurdjevic ainda não, estamos trabalhando nisso.

Este é um problema muito popular e cada atualização notifica 50-100 pessoas. Como agora lançamos o emulador Auth, vou bloquear esse problema para atualizações futuras. Se você tiver uma pergunta, bug ou solicitação de recurso, inicie um novo problema!

Esta página foi útil?
0 / 5 - 0 avaliações