From 6a0b494cd173b22aba35772318fdafa0e787b227 Mon Sep 17 00:00:00 2001 From: Charlie DeTar Date: Tue, 22 Mar 2016 15:54:37 -0600 Subject: [PATCH] Fix tests; tear out farming --- CHANGELOG.md | 11 ++ lib/hangout-farming.js | 114 +---------- package.json | 4 +- public/js/event-app.js | 2 +- test/common.js | 5 + test/test.chat.selenium.js | 5 +- test/test.create-sessions.selenium.js | 3 +- test/test.facilitator-embeds.selenium.js | 5 + test/test.mock-farming.js | 234 ----------------------- test/test.mock-hangout.selenium.js | 2 +- views/event.ejs | 16 -- 11 files changed, 32 insertions(+), 369 deletions(-) create mode 100644 CHANGELOG.md delete mode 100644 test/test.mock-farming.js diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..810399c4 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,11 @@ +## v2.1.0 + + - Upgrade to selenium-server-standalone v2.53.0 and selenium-webdriver v2.47.0. You will likely need to re-download selenium-server-standalone: + + curl -L https://selenium-release.storage.googleapis.com/2.53/selenium-server-standalone-2.53.0.jar > bin/selenium-server-standalone.jar + + - Tear out old farming functionality, which Google broke. See [hangout-farmer](https://github.com/unhangout/hangout-farmer.git) for a temporary workaround until we can replace Google Hangouts. + +## v2.0.0 + + - First version of changelog. diff --git a/lib/hangout-farming.js b/lib/hangout-farming.js index 28209083..f3797bae 100644 --- a/lib/hangout-farming.js +++ b/lib/hangout-farming.js @@ -18,119 +18,7 @@ exports.init = function(app, db, options) { db.redis.llen('global:hangout_urls', function(err, len) { numHangoutUrlsAvailable = len; }); - - // set up an HTTP endpoint that will put us in the endpoint redirect loop - // people who load this url - app.get('/hangout-farming', function(req, res){ - if (!(req.isAuthenticated() && req.user.hasPerm("farmHangouts"))) { - return res.send(401, "Permission Denied"); - } - var url = options.baseUrl + "/hangout-callback"; - - // initialize an oauth client request, using our google client id - oauth2Client = - new googleapis.OAuth2Client( - options.UNHANGOUT_GOOGLE_CLIENT_ID, - options.UNHANGOUT_GOOGLE_CLIENT_SECRET, - url); - - var url = oauth2Client.generateAuthUrl({ - access_type: 'offline', - scope: 'https://www.googleapis.com/auth/calendar' - }); - - // redirect the request to the google calendar api - res.redirect(url); - }); - - var getCalendarEvent = function(code, callback) { - try { - oauth2Client.getToken(code, function(err, token) { - if (err) { return callback(err); } - oauth2Client.credentials = token; - try { - googleapis.discover('calendar', 'v3').execute(function(err, client) { - if (err) { return callback(err); } - try { - var now = moment().format(); - var preppedClient = client.calendar - .events - .insert({calendarId: "primary"}, { - summary: 'hangout', - description: 'hangout', - anyoneCanAddSelf: true, - visibility: "public", - transparency: "transparent", - reminders: { overrides: { method: 'popup', minutes: 0 } }, - start: { - dateTime: moment().add('days', 1).format() - }, - end: { - dateTime: moment().add('days', 1).add('hours', 1).format() - }, - attendees: [] - }).withAuthClient(oauth2Client); - } catch (e) { - return callback(e); - } - try { - preppedClient.execute(function(err, event) { - callback(err, event); - }); - } catch (e) { - return callback(e); - } - }); - } catch (e) { - return callback(e); - } - }); - } catch (e) { - return callback(e); - } - } - // users who complete the authentication request will get redirected back here - // from google, after they authorize our app. The request they make back to - // our server will have a token attached to it, that we will use to - // place requests on behalf of this user. - app.get('/hangout-callback', function(req, res) { - if (!(req.isAuthenticated() && req.user.hasPerm("farmHangouts"))) { - return res.send(401, "Permission Denied"); - } else if (!req.query.code) { - return res.send(400, "Missing code param."); - } - getCalendarEvent(req.query.code, function(err, event) { - if (err) { - logger.error("Error getting calendar event", err); - return res.send(500, "Error getting calendar event: " + JSON.stringify(err)); - } - if("hangoutLink" in event) { - // push it into redis for safekeeping. - db.redis.lpush("global:hangout_urls", event.hangoutLink, function(err, num) { - if (err) { - logger.error("Redis error", err); - return res.send(500, JSON.stringify(err)); - } - // purely for convenience of clicking to farm another url. - res.send("urls available: " + num + - "
CLICK ME"); - - // update the tracking number. - numHangoutUrlsAvailable = num; - logger.analytics("farming", {action: "create", - url: event.hangoutLink, total: num}); - }); - } else { - // we send this error if the calendar event created doesn't have a hangout url - // included in the object. Give the user some rudimentary instructions about - // how to fix this situation. - var msg = "your account doesn't seem to have the 'create video calls for events I create' option enabled. go to google calendar, settings (in the upper right hand corner) and enable that option. Then CLICK HERE!
" + JSON.stringify(event); - logger.error(msg); - res.send(500, msg); - } - }); - }); -} +}; // get a hangout url from redis exports.getNextHangoutUrl = function(callback) { diff --git a/package.json b/package.json index 183df3ff..91798969 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "unhangout-server", - "version": "2.0.0", + "version": "2.1.0", "author": "Drew Harry ", "description": "a server for managing un-hangouts; large scale online un-conference-style events using Google Hangout", "contributors": [ @@ -73,7 +73,7 @@ "expect.js": "0.3.1", "libxmljs": "git://github.com/gwicke/libxmljs.git#7e1ceaf", "mailparser": "~0", - "mocha": "1.18.2", + "mocha": "2.4.5", "selenium-webdriver": "2.47.0", "should": "3.2.0-beta1", "simplesmtp": "~0", diff --git a/public/js/event-app.js b/public/js/event-app.js index b2c007c6..86e5b36e 100644 --- a/public/js/event-app.js +++ b/public/js/event-app.js @@ -329,7 +329,7 @@ $(document).ready(function() { // the server. Showing the admin UI is harmless if a non-admin messes with it. if(IS_ADMIN) { if (NUM_HANGOUT_URLS_WARNING > 0 && NUM_HANGOUT_URLS_AVAILABLE < NUM_HANGOUT_URLS_WARNING) { - $("#no-urls-warning").modal('show'); + console.error("Too few hangout URLS available!", NUM_HANGOUT_URLS_AVAILABLE); } this.adminButtonView = new eventViews.AdminButtonView({ event: curEvent, transport: trans diff --git a/test/common.js b/test/common.js index 6b4a79c8..06d30502 100644 --- a/test/common.js +++ b/test/common.js @@ -78,6 +78,11 @@ var buildBrowser = function(callback) { browser.get(exports.FAST_URL); return browser.executeScript("document.cookie = 'mock_user=; path=/';"); }; + browser.awaitModalDismissal = function(selector) { + return browser.wait(webdriver.until.elementIsNotVisible( + browser.findElement(webdriver.By.css(selector || ".modal"))) + ); + }; // This is sugar to wrap selenium's `wait` with a default timeout. We want // to throw exceptions rather than waiting for mocha's timeout so that we // can see a stack trace (mocha's timeous don't provide one). diff --git a/test/test.chat.selenium.js b/test/test.chat.selenium.js index d6a82add..a7c7f397 100644 --- a/test/test.chat.selenium.js +++ b/test/test.chat.selenium.js @@ -77,7 +77,7 @@ describe("CHAT", function() { browser.executeScript('$("#chat-container-region .panel-body").scrollTop(100)'); checkScroll(browser, false) browser.byCss("#chat-input").sendKeys("msg " + i + "\n"); - checkScroll(browser, true).then(function() { done(); }); + checkScroll(browser, true); browser.executeScript('$("#chat-container-region .panel-body").scrollTop(100)').then(function() {; // Send a message from another user. sock.write(JSON.stringify({ @@ -116,6 +116,9 @@ describe("CHAT", function() { } }); checkScroll(browser, false); + browser.then(function() { + done(); + }); }); diff --git a/test/test.create-sessions.selenium.js b/test/test.create-sessions.selenium.js index c7a16f3e..caf0fe37 100644 --- a/test/test.create-sessions.selenium.js +++ b/test/test.create-sessions.selenium.js @@ -140,7 +140,8 @@ describe("CREATE SESSIONS", function() { browser.byCss("#join_cap").clear(); browser.byCss("#join_cap").sendKeys("wat"); browser.byCss("#join_cap").getAttribute("value").then(function(val) { - expect(val).to.be("wat"); + //expect(val).to.be("wat"); // Recent firefox doesn't allow these chars on number input + expect(val).to.be(""); }); browser.byCss("#create-session").click(); browser.waitForSelector(".join-cap-error"); diff --git a/test/test.facilitator-embeds.selenium.js b/test/test.facilitator-embeds.selenium.js index 5a21bd2b..6a26598b 100644 --- a/test/test.facilitator-embeds.selenium.js +++ b/test/test.facilitator-embeds.selenium.js @@ -57,11 +57,13 @@ describe("FACILITATOR EMBEDS", function() { }); // Remove the embed. + browser.awaitModalDismissal(); browser.byCss(".activity-settings").click(); browser.waitForSelector(".remove-embed"); browser.byCss(".remove-embed").click(); // Ensure 'about' is displayed. + browser.awaitModalDismissal(); browser.waitForSelector(".about-activity"); browser.waitForScript("$"); browser.executeScript("return $('.about-activity').text();").then(function(text) { @@ -77,6 +79,7 @@ describe("FACILITATOR EMBEDS", function() { }); // Add a new activity. + browser.awaitModalDismissal(); browser.byCss(".add-activity").click(); browser.waitForSelector(".add-activity-dialog input[type='text']"); // Doesn't allow blank URL's. @@ -97,6 +100,8 @@ describe("FACILITATOR EMBEDS", function() { }]); }); // Embeds youtube videos. + browser.awaitModalDismissal(".add-activity-dialog"); + browser.waitTime(1000); browser.byCss(".activity-settings").click(); // Can't seem to get around this hard-coded delay; get occasional // "Element is no longer attached to the DOM" errors without it. diff --git a/test/test.mock-farming.js b/test/test.mock-farming.js deleted file mode 100644 index f67088f6..00000000 --- a/test/test.mock-farming.js +++ /dev/null @@ -1,234 +0,0 @@ -var common = require("./common.js"), - expect = require('expect.js'), - request = require('superagent'), - farming = require("../lib/hangout-farming"), - googleapis = require('googleapis'), - async = require('async'); - -var FARM_URL = common.URL + "/hangout-farming"; -var CALLBACK_URL = common.URL + "/hangout-callback"; -var MOCK_AUTH_URL = "http://example.com/mock-auth-url"; -var MOCK_HANGOUT_URL = "http://example.com/mock-hangout-url"; - -/* - * Monkey-patch the google out. - */ - -var LINK_COUNTER = 0; -var CALENDAR_ERROR = null; -var RETURN_CALENDAR_EVENT = true; -var TOKEN_ERROR = null; - -function checkFarmingDb(list, callback) { - common.server.db.redis.lrange("global:hangout_urls", 0, 100, function(err, urls) { - expect(urls).to.eql(list); - callback(err); - }); -}; - -describe("FARMING", function() { - before(function() { - googleapis.OAuth2Client = function() { - this.generateAuthUrl = function() { - return MOCK_AUTH_URL; - }; - this.getToken = function(code, callback) { - return callback(TOKEN_ERROR, "mock-token"); - }; - } - googleapis.discover = function(thingy, version) { - return { - execute: function(callback) { - // Callback with a fake 'client' - return callback(null, { - calendar: { - events: { - insert: function(cal, opts) { - return { - withAuthClient: function(client) { - return { - execute: function(callback) { - var event = {}; - if (RETURN_CALENDAR_EVENT && !CALENDAR_ERROR) { - event.hangoutLink = MOCK_HANGOUT_URL + (++LINK_COUNTER); - } - return callback(CALENDAR_ERROR, event); - } - } - } - } - } - } - } - }); - } - } - }; - }); - beforeEach(function(done) { - common.standardSetup(function() { - common.server.db.users.findWhere({ - "sock-key": "regular1" - }).setPerm("farmHangouts", true); - done(); - }); - }); - afterEach(common.standardShutdown); - - it("test mock setup", function(done) { - var OAuth2Client = require("googleapis").OAuth2Client; - var oauth2Client = new OAuth2Client("client-id", "client-secret", "url"); - expect(oauth2Client.generateAuthUrl({ - access_type: 'offline', - scope: 'https://www.googleapis.com/auth/calendar' - })).to.be(MOCK_AUTH_URL); - expect(oauth2Client.getToken("code", function(err, token) { - expect(err).to.be(null); - expect(token).to.eql("mock-token"); - - TOKEN_ERROR = "error!"; - oauth2Client.getToken("code", function(err, token) { - expect(err).to.be("error!"); - expect(token).to.be("mock-token"); - TOKEN_ERROR = null; - done(); - }); - })); - - }); - - it("denies GET to hangout-farming to those without permission", function(done) { - request.get(FARM_URL) - .set("x-mock-user", "admin1") - .redirects(0) - .end(function(res) { - expect(res.status).to.be(401) - done() - }); - }); - it("denies GET to hangout-callback to those without permission", function(done) { - request.get(CALLBACK_URL) - .set("x-mock-user", "admin1") - .redirects(0) - .end(function(res) { - expect(res.status).to.be(401) - done() - }); - }); - it("allows GET to hangout-farming from superusers", function(done) { - request.get(FARM_URL) - .set("x-mock-user", "superuser1") - .redirects(0) - .end(function(res) { - expect(res.status).to.be(302); - expect(res.headers.location).to.be(MOCK_AUTH_URL); - done(); - }); - }); - it("allows GET to hangout-farming to non-superusers with perms", function(done) { - request.get(FARM_URL) - .set("x-mock-user", "regular1") - .redirects(0) - .end(function(res) { - expect(res.status).to.be(302); - expect(res.headers.location).to.be(MOCK_AUTH_URL); - done(); - }); - }); - it("farms URL with GET to hangout-callback", function(done) { - LINK_COUNTER = 0; - request.get(CALLBACK_URL + "?code=blah") - .set("x-mock-user", "regular1") - .end(function(res) { - expect(res.status).to.be(200); - var count = /urls available: (\d+)/.exec(res.text)[1]; - expect(count).to.be('1'); - expect(farming.getNumHangoutsAvailable()).to.be(1); - checkFarmingDb([MOCK_HANGOUT_URL + "1"], done); - }); - }); - it("displays error on token error", function(done) { - TOKEN_ERROR = "error"; - request.get(CALLBACK_URL + "?code=blah") - .set("x-mock-user", "regular1") - .end(function(res) { - TOKEN_ERROR = null; // reset global error state before any test failure - expect(res.status).to.be(500); - expect(res.text).to.contain("Error"); - expect(farming.getNumHangoutsAvailable()).to.be(0); - checkFarmingDb([], done); - }); - }); - it("displays error on calender error", function(done) { - CALENDAR_ERROR = {message: "error"}; - request.get(CALLBACK_URL + "?code=blah") - .set("x-mock-user", "regular1") - .end(function(res) { - CALENDAR_ERROR = null; // reset global error state before any test failure - expect(res.status).to.be(500); - expect(res.text).to.contain('Error'); - expect(farming.getNumHangoutsAvailable()).to.be(0); - checkFarmingDb([], done); - }); - }); - it("displays an error on non-existing hangout link in event", function(done) { - RETURN_CALENDAR_EVENT = false; - request.get(CALLBACK_URL + "?code=blah") - .set("x-mock-user", "regular1") - .end(function(res) { - RETURN_CALENDAR_EVENT = true; // reset global error state before any test failure - expect(res.status).to.be(500); - expect(res.text).to.contain( - "account doesn't seem to have the 'create video calls") - expect(farming.getNumHangoutsAvailable()).to.be(0); - checkFarmingDb([], done); - }); - }); - it("updates farming count on multiple adds", function(done) { - LINK_COUNTER = 0; - var reqs = [1,2,3,4,5,6,7,8,9,10]; - async.mapSeries(reqs, function(count, done) { - request.get(CALLBACK_URL + "?code=blah") - .set("x-mock-user", "superuser1") - .end(function(res) { - expect(res.status).to.be(200); - expect(res.text.indexOf("urls available: " + count)).to.not.eql(-1); - expect(farming.getNumHangoutsAvailable()).to.be(count); - done(null, res); - }); - }, function(err, results) { - var expectedUrls = []; - for (var i = 0; i < reqs.length; i++) { - expectedUrls.unshift(MOCK_HANGOUT_URL + reqs[i]); - } - checkFarmingDb(expectedUrls, done); - }); - }); - it("updates farming count on consumption and recycling", function(done) { - LINK_COUNTER = 0; - var reqs = [1,2]; - async.mapSeries(reqs, function(count, done) { - request.get(CALLBACK_URL + "?code=blah").set("x-mock-user", "superuser1").end(function(res) { done(); }); - }, function() { - expect(farming.getNumHangoutsAvailable()).to.be(reqs.length); - farming.getNextHangoutUrl(function(err, url) { - expect(url).to.eql(MOCK_HANGOUT_URL + reqs[0]); - expect(farming.getNumHangoutsAvailable()).to.be(reqs.length - 1); - checkFarmingDb([MOCK_HANGOUT_URL + reqs[1]], function() { - farming.reuseUrl(url, function() { - expect(farming.getNumHangoutsAvailable()).to.be(reqs.length); - checkFarmingDb([MOCK_HANGOUT_URL + reqs[1], MOCK_HANGOUT_URL + reqs[0]], done); - }); - }); - }); - }); - }); - it("returns null when no hangout-farming urls are available", function(done) { - // At startup, none are available.. - farming.getNextHangoutUrl(function(err, url) { - expect(err).to.be(null); - expect(url).to.be(null); - done(); - }); - }); -}); diff --git a/test/test.mock-hangout.selenium.js b/test/test.mock-hangout.selenium.js index 2d4ac69f..7cb92a85 100644 --- a/test/test.mock-hangout.selenium.js +++ b/test/test.mock-hangout.selenium.js @@ -49,7 +49,7 @@ describe("MOCK HANGOUT", function() { var url = common.URL + "/test/hangout/" + session.id + "/"; browser.get(url); browser.waitForFunc(function() { - return session.getNumConnectedParticipants() == 1; + return session.getNumConnectedParticipants() == 1 && session.get("hangout-url") !== null; }).then(function() {; expect(session.get("hangout-url")).to.eql(url); expect(session.get("hangout-id")).to.eql(url + "-id"); diff --git a/views/event.ejs b/views/event.ejs index afea1b81..de81292e 100644 --- a/views/event.ejs +++ b/views/event.ejs @@ -1165,22 +1165,6 @@ - - - <% include _video-templates.ejs %>