【问题标题】:Google Authentication with Protractor使用量角器进行 Google 身份验证
【发布时间】:2017-04-27 16:43:39
【问题描述】:

我只能找到this link 来解决我的问题。我正在尝试使用量角器来运行 e2e 测试。这是我第一次尝试,我很喜欢。但是我的项目需要 Google 身份验证,然后一旦通过身份验证,我会将其与我的数据库进行比较,以确保用户在项目中。我无法从 stackoverflow 帖子中弄清楚如何调用最后一个答案中提到的 Google Auth 页面对象。第一个人还说要查找元素 by.id('Email') 和 by.id('Passwd') 这可能是个问题,因为我的谷歌身份验证正在另一个窗口中出现。所以我不知道如何用量角器调用它。这是我在加载 gapi 后初始化 $window 后的一些代码:

.controller('ContainerController', ['$scope', '$rootScope', '$state','$window', '$location','employeeFactory', 'employeeTestFactory', function ($scope, $rootScope, $state, $window,$location, employeeFactory, employeeTestFactory) {
        $rootScope.callRequests=function(){};
        $rootScope.callInfo=function(){};
        if(typeof $rootScope.gapi !== "undefined")gapi.load('client:auth2', initClient);
        $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){
            if(typeof $rootScope.gapi === "undefined") return;
            gapi.load('client:auth2', initClient);
        })
        $scope.$state = $state;
        $window.initGapi = function() {
            gapi.load('client:auth2', initClient);
            $rootScope.gapi = gapi;
        }
        $rootScope.calculateUsed = function(val){
            $rootScope.employee.timePending = $rootScope.employee.timePending = 0;
            var newTimeUsed = 0;
            angular.forEach(val, function(key, value){
                var td = key.timeDuration;
                if(key.timeState === "pending"){
                    $rootScope.employee.timePending += Number(td);
                }else{
                    newTimeUsed += Number(td);
                }
            });
            $rootScope.employee.totalTimeUsed = newTimeUsed;
        }

        $scope.employeeType = $rootScope.email = "";
        function initClient() {
            gapi.client.init({
                apiKey: 'AIzaSyDaMf0eviuFygt1hzwQz03a2k2lrLDnpIc',
                discoveryDocs: ["https://people.googleapis.com/$discovery/rest?version=v1"],
                clientId: '977491754644-954b83j2evmq65v6kchq4dsd9j0ud4vg.apps.googleusercontent.com',
                scope: 'profile'
            }).then(function () {                    gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus);                    updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
                $scope.employee = [];
            });
        }

        function updateSigninStatus(isSignedIn) {
            if (isSignedIn) {
                getEmailAddress();
            }else{
                $state.go('app');
            }
        }

        $scope.handleSignInClick = function(event) {
            if(!gapi.auth2.getAuthInstance().isSignedIn.get()){
                gapi.auth2.getAuthInstance().signIn();
            }
        }

        $scope.handleSignOutClick = function(event) {
            if(gapi.auth2.getAuthInstance().isSignedIn.get()){
                gapi.auth2.getAuthInstance().signOut();
            }
        }

        function getEmailAddress() {
            gapi.client.people.people.get({
                resourceName: 'people/me'
            }).then(function(response) {

                $rootScope.email = response.result.emailAddresses[0].value;
                $rootScope.callRequests();
                $rootScope.callInfo();
        //Here is where I compare google to my db and route users back to main if not in db                employeeTestFactory.get($rootScope.email).then(function(message) {
                    if(typeof message.employeeid === "undefined"){
                        $state.go('app');
                    }else if($location.path() === "/"){
                        $state.go('app.employee');
                        $rootScope.employee = message;

                    }else{
                        $rootScope.employee = message;

                    }
                });

            }, function(reason) {
                console.log('Error: ' + reason.result.error.message);
            });
        }
    }])

    .controller('LoginController', ['$scope', '$state', '$window', '$http','$rootScope', '$timeout', 'GooglePlus', 'gapiService', function ($scope, $state, $window, $http, $rootScope, $timeout, GooglePlus, gapiService) {

        $scope.$state = $state;
        $scope.callme = function(){
            $scope.handleSignInClick();
        }


        // if it could not be loaded, try the rest of
        // the options. if it was, return it.

        var url;
        var windowThatWasOpened;

        $http.get("url").then(function(response) {
            url = response.data;
        });

        $scope.login = function() {
            windowThatWasOpened = $window.open(url, "Please sign in with Google", "width=500px,height=700px");
        }


        window.onmessage = function(e) {

            if(windowThatWasOpened) windowThatWasOpened.close();
            var urlWithCode = e.data;

            var idx = urlWithCode.lastIndexOf("code=");
            if(idx === -1) return;
            var code = urlWithCode.substring(idx + 5).replace("#","");

            $http.get("token?code=" + code).then(function(response) {
                var userurl = 'https://www.googleapis.com/plus/v1/people/me?access_token='+response.data.access_token;
                $http.get(userurl).then(function(response) {
                    console.log("user info: "+JSON.stringify(response.data));
                })
            });


        } 
    }]) 

这是我试图导航到谷歌的代码:

describe('Protractor Demo App', function() {
  it('should have a title', function() {
    browser.get('http://localhost:9000/');

    element(by.id('gLogin')).click().then(function(){
      Google.loginToGoogle();
    });

    expect(browser.getTitle()).toEqual('TrinityIT Time Off Tracking');

     browser.sleep(5000);
  });
});

这是我的 conf 文件:

exports.config = {
  framework: 'jasmine',
  specs: ['googlePage.js','spec.js'],
  onPrepare: function () {
    global.isAngularSite = function (flag) {
      console.log('Switching to ' + (flag ? 'Asynchronous' : 'Synchronous') + ' mode.')
      browser.ignoreSynchronization = !flag;
    },
      global.BROWSER_WAIT = 5000;
  }
}

【问题讨论】:

    标签: angularjs protractor google-oauth


    【解决方案1】:

    假设您要做的是测试您的应用,而不是测试 OAuth 对话,那么有一种更简单的方法。

    首先是 OAuth 复习,完成所有 OAuth 工作的全部意义在于您最终会获得一个访问令牌,您可以将其作为“授权:承载 xxxxx”HTTP 标头包含在您的 Google API(例如 Drive、YouTube 、日历等)请求。太好了,如果您有访问令牌,您可以绕过所有 OAuth 内容,您的应用程序将处于活动状态并能够进行测试。

    所以,您想要的是一种自动获取访问令牌的方法。这很简单。在您的应用代码或 Protractor 序言脚本中的某个地方,您需要获取一个刷新令牌,并使用它来生成一个可用于您的应用的访问令牌。

    我使用文件refreshtoken.js 执行此操作,出于安全原因,我小心地没有将其签入 git。 refreshtoken.js

    var refreshtoken="1x97e978a7a0977...";
    var client_id="423432423@gfgfd";
    

    如果您查看How do I authorise an app (web or installed) without user intervention? (canonical ?) 的答案,您将看到获取刷新令牌的步骤,并在底部显示一些 JavaScript,以展示如何使用刷新令牌获取访问令牌。它可能看起来有很多步骤,但您只需要执行一次,因此不会太繁琐。

    这种方法会绕过 OAuth,因此如果您要测试的是专门的 OAuth,则不是答案。但是,它确实允许您以更健壮的方式测试您的应用程序。它还具有可用于 Karma 单元测试以及 Protractor e2e 测试的好处。

    【讨论】:

    • 抱歉回复晚了。我一直卡在第 9 步,收到以下错误:“oauthplayground,与授权给 OAuth 客户端的不匹配。”我试图使用 gplus 而不是你的链接告诉使用的驱动器。但他们说这对他们中的任何一个人都有效。
    • 确保您在 API 控制台中指定的重定向 URL 完全正确(逐个字符)“developers.google.com/oauthplayground
    • 是的,我想我需要添加“量角器序言脚本”来获取刷新令牌。你能指点我一个地方来解决这个问题吗?
    • 获取访问令牌的 JS 在我链接到的 SO 问题中。 Tiy 可能会将其放入 onPrepare - 请参阅 github.com/angular/protractor/blob/master/spec/withLoginConf.js
    • 我从其他页面的代码中收到错误消息。说“标题未定义”。我发现这是实验代码,它可以与 Protractor 一起使用吗?
    猜你喜欢
    • 2017-03-11
    • 2018-10-19
    • 1970-01-01
    • 2019-08-15
    • 2012-04-23
    • 2011-10-20
    • 2014-09-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多