使用量角器进行Google身份验证

时间:2017-04-26 16:22:34

标签: angularjs protractor google-oauth

我只能追踪this link来解决我的问题。我正在尝试使用量角器来运行e2e测试。这是我的第一次,我喜欢它。但是我的项目需要Google身份验证,然后经过身份验证后,我会将其与我的数据库进行比较,以确保用户在项目中。我无法从stackoverflow帖子中弄清楚如何调用Google Auth页面对象demee在最后一个答案中正在讨论。另外第一个人说找到元素by.id('电子邮件')和by.id(' Passwd')这可能是一个问题,因为我的谷歌认证正在另一个窗口。因此我不确定如何使用Protractor调用它。这是我加载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;
  }
}

1 个答案:

答案 0 :(得分:3)

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

首先是OAuth复习,完成所有OAuth工作的重点在于您最终获得了一个访问令牌,您可以将其包含为"授权:Bearer xxxxx"带有Google API的HTTP标头(例如,云端硬盘,YouTube,日历等)请求。 Sooooooo,如果你有一个访问令牌,你可以绕过所有的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测试的优点。