Firebase-tools: Добавить эмулятор аутентификации firebase в набор эмуляторов

Созданный на 26 сент. 2019  ·  66Комментарии  ·  Источник: firebase/firebase-tools

Можно ли эмулировать API аутентификации для более быстрой локальной разработки и сквозного тестирования? С эмулятором Firestore нам не нужно создавать разные проекты для разных сред (dev, testing, staging, prod), мы можем просто использовать эмулятор, заполнять его данными из файлов JSON в режиме просмотра для разработки или заполнять для каждого тестовый пример и т. д. Чтобы иметь возможность написать сквозной тест, в котором есть вход пользователя, навигация на основе роли, а затем некоторые действия, мы должны создать отдельный проект для изоляции тестовых пользователей, а также заполнить и очистить пользователей оттуда. для каждого тестового примера.

emulator-suite feature request

Самый полезный комментарий

Мы усиленно работаем над эмулятором полной аутентификации, который, будем надеяться, будет тем,
каждый хочет. Нет графика, который я могу предложить прямо сейчас, но это высокий приоритет
для нас.

Пт, 22 мая 2020 г., в 8:12 ChuckB [email protected] написал:

@samtstern https://github.com/samtstern Любой прогресс или другой
решение этой проблемы / особенности? Мне нужно (1) setEmulatedUser для работы с
эмулятор облачного Firestore, чтобы я мог проводить локальное ручное тестирование.

На ваш комментарий: 17 октября 2019 г.
_Я думаю, что (2) - правильная история, но я пытался понять
сколько людей были бы довольны (1), поскольку значительно проще
внедрять и поддерживать.

(1) Войдите в систему, чтобы использовать такие службы, как Firestore или Realtime Database, без
фактически создавая реальных пользователей. Прямо сейчас вот что-то вроде
setEmulatedUser решит. Это просто позволит вам получить поддельную аутентификацию
локальный токен, который эмуляторы примут, но он будет отклонен
прод. Больше безопасности, больше изоляции и т. Д. _

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/firebase/firebase-tools/issues/1677#issuecomment-632660684 ,
или отказаться от подписки
https://github.com/notifications/unsubscribe-auth/ACATB2Q4LV7NXMQFEALNPXLRSZT25ANCNFSM4I27PTFA
.

Все 66 Комментарий

@vladimirdjurdjevic, спасибо, что подняли этот вопрос! Это в нашем списке вещей, которые нужно сделать, но мы еще не решили, какую часть службы аутентификации нужно подражать, и какую стратегию это лучше всего сделать. Некоторые вещи (например, анонимную аутентификацию) очень легко подражать, в то время как другие (например, аутентификация по SMS) очень сложно.

Но мы определенно хотим включить упомянутый вами вариант сквозного использования!

Вопрос: было бы вам полезно, если бы существовала библиотека, позволяющая локально имитировать пользователя Firebase для использования с эмуляторами? Что-то вроде:

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

@samtstern Будет ли вызов setEmulatedUser() также запускать какие-либо эмулируемые облачные функции functions.auth.user().onCreate() ? Если так, это было бы очень полезно.

@samtstern Это наверняка поможет некоторым сценариям тестирования, но для разработки все же потребуется реальный экземпляр. Моя идея состоит в том, чтобы избежать создания нескольких проектов Firebase для разных сред и иметь возможность разрабатывать локально (возможно, в автономном режиме). Другой подход заключался бы в поддержке различных сред для сервисов. Если бы мы могли создать разные среды, скажем, для firestore и auth в одном проекте, это решило бы многие проблемы. Я знаю, что могу создать проект для каждой среды, но это настоящая заноза в заднице. Настройка каждой среды, репликация данных и т. Д. В идеале я хотел бы иметь возможность создать один проект firebase, и если мне нужны фиктивные данные для ручного тестирования, я мог бы просто создать промежуточную среду для firestore и загружать туда данные.

@noelmansour хороший вопрос! Это было бы несложно сделать, нам, вероятно, понадобятся два разных вызова, например signInAsEmulatedUser и signUpAsEmulatedUser где только второй запускает функцию.

@vladimirdjurdjevic полностью согласен с тем, что полнофункциональный эмулятор лучше всего. Не могли бы вы объяснить, какие вещи вам понадобятся от «реального экземпляра для разработки», которые не решаются путем локальной настройки пользователя?

Вопрос: было бы вам полезно, если бы существовала библиотека, позволяющая локально имитировать пользователя Firebase для использования с эмуляторами?

Действительно полезно, это очень поможет.
Прямо сейчас я просто устанавливаю на true функцию правила, проверяющую зарегистрированного пользователя каждый раз, когда мне нужно что-то протестировать локально, это довольно небезопасно, но, вероятно, более простая вещь, которую я могу сделать без эмуляции текущего пользователя.

Да, это было бы невероятно полезно

Я также хотел бы провести модульный тест functions.auth.user().onCreate() . Я полагаю, что сейчас лучший обходной путь - это, по сути, функция обратного вызова экспорта, переданная в onCreate и предоставление ей поддельного объекта user .

Для такого рода модульного тестирования ознакомьтесь с firebase-functions-test
библиотека, которая помогает вызывать обработчики функций с фиктивными данными.

Вс, 13 октября 2019 г., 5:44 Даниэль К. [email protected] написал:

Я также хотел бы провести модульное тестирование functions.auth.user (). OnCreate (). я
предположим, что сейчас лучший обходной путь - это обратный вызов экспорта
функция, переданная onCreate, и предоставит ей фальшивый пользовательский объект.

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/firebase/firebase-tools/issues/1677?email_source=notifications&email_token=ACATB2QYJLX2LNVDTWJV25TQOMJ4VA5CNFSM4I27PTFKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEBCVQIQ#issuecomment-541415458 ,
или отказаться от подписки
https://github.com/notifications/unsubscribe-auth/ACATB2SO3IR6UB73F4EMZPTQOMJ4VANCNFSM4I27PTFA
.

@samtstern Это действительно работает вместе с эмулятором Firestore? На основании этого у меня сложилось впечатление, что это для других целей.

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

Мне, конечно, не нужен онлайн-режим для модульного тестирования, это было бы медленно. И я не уверен, что могу получить доступ к эмулятору Firestore с помощью «заглушки».

@FredyC спасибо, что указали на эти документы. Используемые слова сбивают с толку, потому что «режимы» - это не переключатель, который вы можете включить, они просто описывают стратегии, которые вы можете использовать.

Если бы вы запускали эмулятор Firestore вместе с модульными тестами, ваш код определенно мог бы подключиться к нему. Если вы установите переменную среды FIRESTORE_EMULATOR_HOST Firebase Admin SDK автоматически подключится к эмулятору Firestore ( firebase emulators:exec сделает это за вас).

@samtstern У меня все еще возникают проблемы с подключением точек, и как все это поможет мне протестировать functions.auth.user().onCreate() ? Я имею в виду, что это здорово, что функции будут подключаться к эмулятору, а не к производственной версии, но это только Firestore, верно? Как мне вызвать создание пользователя из тестов, чтобы на самом деле запустить код функции?

Кажется, что в упомянутом тесте firebase-functions-test есть какой-то загадочный метод makeUserRecord , но не имеет особого смысла, как это будет работать или как его фактически использовать.

Я попытался вызвать auth.createUserWithEmailAndPassword() из пакета @firebase/testing , но он жалуется на неверный ключ API, поэтому я предполагаю, что он будет работать только с онлайн-версией.

Когда я ищу в org ту переменную env, которую вы упомянули, она обнаруживается только в трех местах, и ни одна из них не имеет отношения к auth. Если только он не скрыт некоторой конкатенацией строк.

Я также просматривал https://github.com/firebase/functions-samples, но не нашел там примеров модульного тестирования.

Не могли бы вы разобраться в этом? :)

У меня также есть другой случай, несколько противоположный, когда код облачной функции использует вызов admin.auth().getUserByEmail() . Удивительно, но это не заканчивается ошибкой, но я понятия не имею, как создать этого пользователя, чтобы его можно было вернуть. Кроме, конечно, насмешки над всем админским модулем, но это безумие :)

@samtstern Приносим извинения за задержку. Когда я говорю реальный экземпляр, я имею в виду реальный экземпляр: D В идеале я просто хочу поменять местами конфигурацию в моем файле окружения angular для разработки и продолжать реализовывать функции аутентификации, например, мое приложение обращается к реальному API, но на самом деле это эмулятор, работающий на моем машина, и я могу делать это в автономном режиме. Теперь я понимаю проблемы с отправкой SMS, например. Было бы глупо ожидать, что эмулятор отправит настоящее SMS на мой телефон, но вы могли бы просто распечатать его на консоли (содержимое SMS, которое будет отправлено). Это, вероятно, больше хлопот, чем ценность этого. Вот почему я думаю, что простая поддержка нескольких сред для каждого проекта может сделать все намного лучше. Репликация конфигураций между несколькими проектами для разных сред занимает слишком много времени. А также управление несколькими учетными записями служб для сценариев, чтобы иметь возможность передавать данные в разные проекты Firestore, является проблемой. Вот почему я учил, что если бы у нас была эмулирована вся платформа firebase, мы могли бы использовать ее для каждой непроизводственной среды и управлять только одним настоящим проектом firebase. Но, возможно, просто поддержка нескольких сред для каждого проекта - лучшее решение с приемлемым результатом.

@FredyC благодарим за отзывы! Нам действительно полезно увидеть, насколько это может сбивать с толку. Есть две основные вещи, которые люди хотят делать в своих тестах, связанных с аутентификацией:

  1. Войдите в систему, чтобы использовать такие службы, как Firestore или Realtime Database, не создавая реальных пользователей. Прямо сейчас это то, что решило бы что-то вроде setEmulatedUser . Это просто позволит вам иметь фальшивый токен аутентификации локально, который эмуляторы примут, но он будет отклонен prod. Больше безопасности, больше изоляции и т. Д.
  2. Фактически тестируйте аутентификацию напрямую. В нем будет несколько частей:
    а. Эмулятор аутентификации, который отвечает на все необходимые вызовы API, чтобы вы могли указать на него пакеты SDK аутентификации.
    б. Интеграция между этим эмулятором и эмулятором функций, чтобы .onCreate функции запускались правильно.
    c. Автоматическая фиксация внутри эмулятора функций, так что admin.auth() указывает на эмулятор Auth, точно так же, как мы делаем это сегодня для Firestore и RTDB.

Я думаю, что (2) - правильная история, но я пытался понять, сколько людей были бы довольны (1), поскольку его значительно проще реализовать и поддерживать.

@samtstern Понятно . Поправьте меня, если я ошибаюсь, но разве (1) еще не решен? Я имею в виду, что в тестах я могу просто вызвать следующее, и эмулятор Firestore распознает меня как этого пользователя, чтобы я мог проверить правила безопасности. На самом деле я еще не пробовал, но пока выглядит многообещающе :)

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

(2) определенно звучит очень полезно, но наверняка намного сложнее справиться. К сожалению, мое понимание всего продукта настолько ограничено, что я не могу предложить здесь никаких полезных идей.

Думаю, надо строить постепенно. Вместо того, чтобы пытаться охватить все сценарии сразу, создайте его на основе известных вариантов использования и добавляйте на ходу. По моему ограниченному мнению, имитировать «базу данных пользователей» вместе с триггерами функций не так уж сложно.

@FredyC, вы правы, что (1) разрешено для использования внутри тестовых наборов. Но другой вариант использования - это подключение вашего Android / iOS / Web-приложения напрямую к эмулятору для локальной разработки. В этом случае вы не можете использовать @firebase/testing .

Понятно. Честно говоря, было бы замечательно, если бы @firebase/testing можно было бы использовать кросс-платформенный вместо отдельных решений. Я имею в виду, насколько сложно перенаправить общение на эмулятор? Разве FIRESTORE_EMULATOR_HOST для этого? Хотя я думаю, что что-то вроде FIREBASE_EMULATOR_HOST было бы более подходящим, если бы в эмуляторе были и другие службы.

@vladimirdjurdjevic Я думаю, не сработает ли фактически signInWithPhone чтобы вы могли контролировать его поведение? Тогда вам не нужно беспокоиться об эмуляторе и получении смс-кода в консоли :)

Конечно, тогда вам понадобится какой-то способ аутентифицироваться в эмуляторе Firestore (и подключиться к нему). Что-то вроде того, что я описал в предыдущем https://github.com/firebase/firebase-tools/issues/1677#issuecomment -542897671. Существует базовый метод создания незащищенных токенов: https://github.com/firebase/firebase-js-sdk/blob/master/packages/testing/src/api/index.ts#L64. Не уверен, что это сработает.

Конечно, издевательство над сторонними библиотеками не всегда так просто, но если разобраться, то это может принести отличные результаты. В конце концов, его можно было извлечь в какую-нибудь библиотеку, чтобы в целом было проще.

Я также думаю, что эти методы входа могут вызывать множество кодов ошибок, о чем также должны позаботиться надлежащие тесты. Это легко сделать и с издевательством.

@samtstern Расширение контекста пространства имен firebase.auth() чем-то актуальным, например setEmulatedUser похоже на анти-шаблон с существующими стратегиями эмуляции. Возможно, на эту рекомендацию повлияла простота расширения на стороне пакета?

В соответствии с другими эмуляторами, я ожидал бы, что отдельный уровень службы аутентификации будет запущен через HTTP, а конфигурация на стороне клиента может перенаправить существующую поверхность API для использования.

Я бы предпочел, чтобы эксцентричные случаи AuthN возвращали ошибки с Admin и Client API, минимально поддерживающими CRUD для базовых пользователей по имени пользователя / паролю. Черт возьми, я думаю, что даже начиная с поддержки Custom Token в Admin и signInWithCustomToken было бы очень далеко. Возможно, реализовать низко висящие плоды с помощью матрицы поддержки API, опубликованной в документации.

Что касается точки аутентификации интеграции заключается в условном импорте @firebase/testing в код приложения для маршрутизации к пользовательскому вызову initializeTestApp . Это действие одновременно подчеркивает исключение пакетов во время сборки для проектных групп, а также распределяет конфигурации перенаправления эмулятора между двумя API-интерфейсами пакетов ( initializeTestApp и firestore.settings / functions.useFunctionsEmulator ).

Взломайте планету!

текущая стратегия тестирования аутентификации интеграции заключается в условном импорте @firebase/testing в код приложения для маршрутизации к пользовательскому вызову initializeTestApp .

Гм, я вызываю этот метод внутри тестов. Хитрость в том, что обычный initializeApp находится в index.ts который импортирует функции. Он вызывается при запуске эмулятора, но когда тесты выполняются, это другой процесс, и он не конфликтует друг с другом. Так что бремени условного импорта действительно нет.

Конечно, это может быть иначе для тестирования аутентификации, например. веб-приложение, в котором исполнитель тестов поделится процессом с кодом приложения. Однако при модульном тестировании вы обычно не импортируете в тест целое приложение. initializeApp , вероятно, выполняется в каком-то коде, который не имеет отношения к тестам и вообще не импортируется.

@FredyC Согласен с документированным использованием модульных тестов. На самом деле говорил о сценариях полного приложения, в которых API расходятся, а динамический импорт выходит за рамки документированной карты.

Я просто хотел дать вам указание на Honestly, it would be kinda superb if @firebase/testing could be used cross-platform instead of having separate solutions . цифровая высокая пятерка

@FredyC благодарим за отзывы! Нам действительно полезно увидеть, насколько это может сбивать с толку. Есть две основные вещи, которые люди хотят делать в своих тестах, связанных с аутентификацией:

  1. Войдите в систему, чтобы использовать такие службы, как Firestore или Realtime Database, не создавая реальных пользователей. Прямо сейчас это то, что решило бы что-то вроде setEmulatedUser . Это просто позволит вам иметь фальшивый токен аутентификации локально, который эмуляторы примут, но он будет отклонен prod. Больше безопасности, больше изоляции и т. Д.
  2. Фактически тестируйте аутентификацию напрямую. В нем будет несколько частей:
    а. Эмулятор аутентификации, который отвечает на все необходимые вызовы API, чтобы вы могли указать на него пакеты SDK аутентификации.
    б. Интеграция между этим эмулятором и эмулятором функций, чтобы .onCreate функции запускались правильно.
    c. Автоматическая фиксация внутри эмулятора функций, так что admin.auth() указывает на эмулятор Auth, точно так же, как мы делаем это сегодня для Firestore и RTDB.

Я думаю, что (2) - правильная история, но я пытался понять, сколько людей были бы довольны (1), поскольку его значительно проще реализовать и поддерживать.

@samtstern, в первую очередь, я бы хотел иметь такую ​​эмуляцию.

Я бы не увидел. 1 очень полезен для написания тестов e2e. В настоящее время мне нужно использовать реальный экземпляр для аутентификации, в то время как я могу использовать эмулятор для хостинга, правил, хранилища огня и функций.

Я думаю, что можно использовать setEmulatedUser для имитации пользователя так же, как это делается в firebase.initializeTestApp. Должна быть предусмотрена возможность отправки, например, пользовательских токенов и других данных, связанных с пользователем.

Также должна быть возможность получить образцы учетных данных, которые можно использовать в клиентском приложении с помощью firebase.auth().signInWithCredential(credential)

Спасибо @vladimirdjurdjevic за то, что подняли этот вопрос! Уже почти год искали решение.

Хотелось бы увидеть настоящий эмулятор для трех вещей:

  1. e2e тестирует все приложение, поэтому нам не нужно создавать разные среды, как сказал @vladimirdjurdjevic .
  2. Интеграционные тесты для бэкэнда, где вызываются API и пользователь должен пройти проверку в Firebase.
  3. Все наши разработчики во время разработки используют центральную среду Firebase, что вызывает множество конфликтов. Конечно, каждый разработчик может создать свой собственный проект Firebase, но им все равно нужно управлять своими тестовыми пользователями на панели управления Firebase, что не идеально. Кроме того, мы хотели бы разрабатывать наше приложение в автономном режиме, что сегодня невозможно из-за отсутствия реального эмулятора.

Надеюсь, что вы скоро для нас что-то выпустите, это сделает ваш продукт более ценным! В таких сервисах очень важна продуктивность разработчиков!

Кажется, это особенность в списке желаний многих людей. Firebase auth сейчас кажется IDaaS №1 по ценообразованию, так что это действительно проблема, которую вы не можете разрабатывать локально с помощью облачных функций. Надеюсь, у команды FB скоро будут для нас обновления! 🙏

Изменить: Pinging @mbleigh из @ firebase-ops, так как этот поток похоронен под проблемами ...

У меня также есть эта ошибка ... функция игнорируется, потому что эмулятор аутентификации не существует или не запущен.

это запускается этим кодом:

functions.auth.user (). onDelete ()

любая информация по этому поводу ...

@dominikfoldi

Я согласен с вашими пунктами. Один совет, который может вам помочь:

Конечно, каждый разработчик может создать свой собственный проект Firebase, но им все равно нужно управлять своими тестовыми пользователями на панели управления Firebase, что не идеально.

Вы можете набирать пользователей и управлять ими программно с помощью административного SDK firebase, например auth().createUser , см. Также https://firebase.google.com/docs/auth/admin/manage-users

После прочтения этой ветки я думаю, что люди здесь могут найти Foundry полезной.

Я один из соучредителей Foundry. Foundry - это инструмент CLI, который берет ваши облачные функции Firebase и создает копию вашего производственного приложения Firebase на наших серверах, которые действуют как среда разработки, в которой вы напрямую запускаете свой код. Конфигурация не требуется.

Foundry следит за вашими файлами исходного кода, и каждый раз, когда вы сохраняете свой код локально, мы запускаем его на наших серверах и возвращаем вам результаты всего за несколько секунд. Все супер быстро.
Вы указываете, какие данные Firestore, RealtimeDB и Auth Users должны быть скопированы из вашего производственного приложения через наш файл YAML, чтобы они были доступны во время разработки.

 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}

Вы также указываете, как мы должны запускать ваши облачные функции при запуске вашего кода. Он работает как REPL для ваших облачных функций. Таким образом, вы всегда будете уверены, что ваши облачные функции будут правильно работать с производственными данными и в производственной среде после их развертывания.
Кроме того, ваши облачные функции действуют так, как если бы они были развернуты.

Эти среды разработки создаются специально при запуске сеанса. Таким образом, каждый в вашей команде работает в своей собственной среде, где они могут бездельничать.

Я не хочу спамить здесь обсуждение, поэтому не стесняйтесь, [email protected]
Я более чем счастлив помочь вам настроить Foundry в ваших проектах, просто отправьте мне письмо по электронной почте!

Тем не менее, судя по тому, как вы это описали и что я прочитал на домашней странице, эта служба является облачной.
Эмулятор Firebase вместо этого работает даже в автономном режиме, поэтому его можно использовать для автоматического тестирования.

@samtstern Есть ли прогресс или другое решение этой проблемы / функции? Мне нужно (1) setEmulatedUser для работы с эмулятором облачного Firestore, чтобы я мог проводить ручное тестирование локально. Другой вариант - иметь аргумент командной строки, который устанавливает идентификатор пользователя при запуске эмулятора. Таким образом, эмулятор будет работать под идентификатором пользователя, переданным при запуске. Таким образом, правила могут быть проверены на местном уровне.

На ваш комментарий: 17 октября 2019 г.
_Я думаю, что (2) - правильная история, но я пытался понять, сколько людей были бы довольны (1), так как это значительно проще реализовать и поддерживать.

(1) Войдите в систему, чтобы использовать такие службы, как Firestore или Realtime Database, не создавая реальных пользователей. Прямо сейчас это то, что решило бы что-то вроде setEmulatedUser. Это просто позволит вам иметь фальшивый токен аутентификации локально, который эмуляторы примут, но он будет отклонен prod. Больше безопасности, больше изоляции и т. Д. _

Мы усиленно работаем над эмулятором полной аутентификации, который, будем надеяться, будет тем,
каждый хочет. Нет графика, который я могу предложить прямо сейчас, но это высокий приоритет
для нас.

Пт, 22 мая 2020 г., в 8:12 ChuckB [email protected] написал:

@samtstern https://github.com/samtstern Любой прогресс или другой
решение этой проблемы / особенности? Мне нужно (1) setEmulatedUser для работы с
эмулятор облачного Firestore, чтобы я мог проводить локальное ручное тестирование.

На ваш комментарий: 17 октября 2019 г.
_Я думаю, что (2) - правильная история, но я пытался понять
сколько людей были бы довольны (1), поскольку значительно проще
внедрять и поддерживать.

(1) Войдите в систему, чтобы использовать такие службы, как Firestore или Realtime Database, без
фактически создавая реальных пользователей. Прямо сейчас вот что-то вроде
setEmulatedUser решит. Это просто позволит вам получить поддельную аутентификацию
локальный токен, который эмуляторы примут, но он будет отклонен
прод. Больше безопасности, больше изоляции и т. Д. _

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/firebase/firebase-tools/issues/1677#issuecomment-632660684 ,
или отказаться от подписки
https://github.com/notifications/unsubscribe-auth/ACATB2Q4LV7NXMQFEALNPXLRSZT25ANCNFSM4I27PTFA
.

1. Войдите в систему, чтобы использовать такие службы, как Firestore или Realtime Database, не создавая реальных пользователей. Прямо сейчас это то, что решило бы что-то вроде setEmulatedUser. Это просто позволит вам иметь фальшивый токен аутентификации локально, который эмуляторы примут, но он будет отклонен prod. Больше безопасности, больше изоляции и т. Д.

Я был бы счастлив с номером 1 здесь, тем временем

@ rishisingh-dev невозможно запустить эмулятор аутентификации, потому что эмуляторы firebase в настоящее время его не поставляют.

Но вполне возможно протестировать облачные функции, которые включают в себя аутентификацию. Вы можете выполнить рефакторинг функции, для которой требуется некоторый API аутентификации, и смоделировать ее в тестах, предоставив реальную функцию в файле функций firebase. Точность вашей тестовой настройки ниже, но тогда это становится вопросом степени, а не вида: вы просто тестируете вызовы аутентификации напрямую, но вы можете проверить то, что вы ожидаете от них.

В этом вопросе SO это будет примерно так:

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

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

И в своих тестах вы вызываете sendWelcomeEmail напрямую, чтобы убедиться, что он выполняет то, что вам нужно.

Представьте, что у вас есть более сложная облачная функция под названием addFriend , где пользователь вводит электронное письмо друга, а вам нужен uid. Вы можете получить это через 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 ) };
}

В облачном объявлении fn вы отправляете реальный getUserByEmail , но в ваших тестах вы вместо этого отправляете поддельный:

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

Я не думаю, что это существенно отличается от тестирования любого стороннего API в модульном тесте. Наличие у эмуляторов firebase возможности аутентификации удаляет шаблонный код для сценариев сквозного тестирования, но это не меняет существенно модульные тесты, поскольку вы все равно не хотите, чтобы постоянное состояние сохранялось между тестами.

Я бы хотел иметь возможность запускать это локально без необходимости загружать в облако для проверки

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 })
}

Кстати, можно ли получить user.displayName внутри функции onCreate?

да, если он установлен, думаю, вы пробовали?

Да, возвращает ноль.
Я пробовал это в облаке (не локально).

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

Мой код здесь.

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

Интересно, что я не использую отображаемое имя, я использую пользовательское имя пользователя для
БД в реальном времени

/**
 * 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)
    }
}

Пт, 10 июл 2020, 10:44, rishisingh-dev [email protected]
написал:

Да, возвращает ноль.
Я пробовал это в облаке (не локально).

[Изображение: снимок экрана 2020-07-10 в 2 43 12 AM]
https://user-images.githubusercontent.com/56976320/87140958-29f3ac80-c257-11ea-98d3-084fad619de7.png

Мой код здесь.

console.log (user.uid);
console.log (user.email);
console.log (имя_пользователя);
}); `` `

-
Вы получаете это, потому что подписаны на эту беседу.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/firebase/firebase-tools/issues/1677#issuecomment-656587759 ,
или отказаться от подписки
https://github.com/notifications/unsubscribe-auth/AABU35Q27EMMHYAYU5CNZR3R23PIDANCNFSM4I27PTFA
.

>

С уважением

Никос Кациканис

Да, моей основной целью было обновление базы данных пользовательской информацией внутри функции onCreate .
Но поскольку я не могу получить displayName , я сделал функцию onCallable и сделал это.

Спасибо.

@samtstern Я очень рад видеть, что вы работаете над этим :) Только что начал новый проект с firebase, и опыт разработчиков уже намного лучше (с пользовательским интерфейсом эмулятора и опцией --inspect-functions). С нетерпением жду возможности увидеть эмулятор аутентификации в действии :) Отличная работа!

еще одна лучшая вещь - мне не нужно открывать хром без защиты

@samtstern

Через два месяца можно ли сейчас дать приблизительную оценку?

Мы хотели бы отгрузить в начале следующего года. Теперь мы стоим перед решением, начнем ли мы писать интеграционные тесты для реального проекта или подождем несколько месяцев для эмулятора аутентификации. Не могли бы вы нам немного помочь?

Лучший,

Никлас

Наша политика в Firebase - не давать оценки того, когда что-то будет запущено, если мы не уверены на 100%. Прямо сейчас мы усердно работаем над эмулятором Auth, но мы еще недостаточно близки к завершению, чтобы выбрать дату запуска.

Это один из наших главных приоритетов, но я думаю, вам не следует ждать, пока мы начнем тестирование вашего приложения. Напишите свои тесты против prod сегодня, переключите их на эмулятор, когда он будет доступен.

Хорошо, спасибо @samtstern. Что помогает!

Мы действительно хотели бы использовать эмулятор аутентификации для тестирования облачных функций и запросов Firestore, которые включают настраиваемые утверждения для пользовательских токенов. Мы можем сортировать тестовые пользовательские утверждения с помощью Firestore на игровой площадке правил в Firebase Console, но полноценный эмулятор аутентификации теоретически позволит нам сделать гораздо больше в плане тестирования, когда дело доходит до пользовательских токенов.

Чтобы было ясно: мы стремимся к полноценному эмулятору аутентификации, который имитирует фактические конечные точки службы (где это возможно). Мы больше не рассматриваем что-то легкое, как предлагали мои предыдущие комментарии .

@samtstern , это приятно слышать (вместе с пользовательскими утверждениями, поскольку это часто используется со сторонними интеграциями). Есть ли где-нибудь, где мы можем идти в ногу с прогрессом / расчетным временем прибытия?

@fandy, извини, нам пока не чем поделиться ...

Спасибо, Сэм, в настоящее время я провожу все свои испытания вручную, потому что это не так.
стоит усилий написать тесты e2e без аутентификационных моков

В среду, 26 августа 2020 года, в 14:32, Сэм Стерн [email protected] написал:

>
>

@fandy https://github.com/fandy извините, нам не к чему
поделитесь еще ...

-
Вы получаете это, потому что подписаны на эту беседу.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/firebase/firebase-tools/issues/1677#issuecomment-680850282 ,
или отказаться от подписки
https://github.com/notifications/unsubscribe-auth/AABU35UAQDBYEXKKINJSM43SCT6E7ANCNFSM4I27PTFA
.

-

С уважением

Никос Кациканис

Чтобы обойти это, я экспериментировал с импортом @ firebase / testing в браузере. На самом деле это не сработало. Это, однако, делает: mangle @ firebase / testing source, чтобы скопировать следующий слегка отредактированный фрагмент:

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)
}

Теперь в коде вашего приложения на стороне браузера вы можете импортировать это, и

  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

Это прекрасно работает! Теперь, когда я работаю в разработке, у меня есть локальный поддельный пользователь, которого эмулятор считает «testuser» (как показано в руководстве по тестированию правил безопасности firestore).

Другой обходной путь, который я использую, - это заглушить вашу аутентификацию (я использую сгенерированных поддельных пользователей для тестов).

Пример 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

Также измените свои правила, поскольку auth.token не эмулируется. Например:

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 })

У меня это отлично работает. Надеюсь, это поможет…

Если вы подписаны на эту тему и хотите стать альфа-тестером эмулятора аутентификации Firebase, выполните следующие действия:

  1. Зарегистрируйтесь в программе Firebase Alpha: https://services.google.com/fb/forms/firebasealphaprogram/
  2. Отправьте мне электронное письмо на [email protected] , обязательно отправьте его с адреса электронной почты, который вы будете использовать для тестирования.

Пожалуйста, делайте это только в том случае, если вы серьезно заинтересованы в опробовании эмулятора на ранней стадии и предоставлении обратной связи! Будут ошибки, и некоторые части настройки будут сложными, но мы хотим знать, что вы думаете.

@samtstern Это отличная новость! Я бы с удовольствием попробовал его, но к концу недели я собираюсь приступить к производству своего текущего проекта, поэтому сейчас я не могу позволить себе поиграть с ним. Запишусь на альфу, как только смогу :) Спасибо за отличную работу.

100% захотят это попробовать! твой мужчина Сэм!

@samtstern с нетерпением жду возможности попробовать и помочь всем, чем могу!

Мне нужно использовать функцию аутентификации для локального тестирования функций с Android, контекст Auth всегда равен нулю

Хорошие новости: Эмулятор аутентификации является частью свежего выпуска 8.14.0 ! 🙌🎊

Спасибо за тяжелую работу, ребята и @samtstern 💪

классные ребята!

Я всего лишь посыльный! Эмулятор Auth на 99% построен @yuchenshi ... и поэтому я позволю ему закрыть эту проблему, когда он проснется.

Есть ли документация по этому новому эмулятору? (как установить, настроить клиентов и т. д.)

PST Большое спасибо за всю тяжелую работу над этим. Это позволит нам получить массу интересных вещей.

@nicoburns очень скоро! Официальное объявление, документы и все остальное в ближайшее время.

Отличные новости! :) Не могу дождаться, чтобы попробовать :)

Я знаю, что вы этого ждали, так что давайте сразу перейдем к делу:

  • Эмулятор аутентификации Firebase теперь доступен. Вы можете получить его, установив Firebase CLI> = v8.14.0.
  • Следуйте руководству по Emulator Suite, чтобы начать работу , и подключите свои приложения .
  • Чтобы получать такие захватывающие объявления, как эта, и многое другое, подпишитесь на прямую трансляцию Firebase Summit ПРЯМО СЕЙЧАС. **

** Бесстыдный плагин: сегодня я также провожу сеанс на тему «Как настроить CI с помощью набора эмуляторов Firebase». Найти это в расписании сеансов оставлено в качестве упражнения для читателя.


_P.S. Я действительно не могу принять 99% заслуг, так как Эмулятор Auth, конечно же, работает в команде. Различные люди из разработчиков Firebase и Firebase (вы) тоже сыграли большую роль в этом. Спасибо!_

@yuchenshi Можно ли экспортировать созданных пользователей при выходе, как в эмуляторе firestore?

@vdjurdjevic еще нет, мы над этим работаем.

Это действительно популярная проблема, и каждое обновление уведомляет 50-100 человек. Поскольку мы выпустили эмулятор Auth, я собираюсь заблокировать эту проблему от будущих обновлений. Если у вас есть вопрос, ошибка или запрос функции, начните новый выпуск!

Была ли эта страница полезной?
0 / 5 - 0 рейтинги