diff --git a/jupyterhub/tests/mocking.py b/jupyterhub/tests/mocking.py index 792779e5..44119ae7 100644 --- a/jupyterhub/tests/mocking.py +++ b/jupyterhub/tests/mocking.py @@ -74,18 +74,20 @@ def mock_open_session(username, service, encoding): class MockSpawner(LocalProcessSpawner): """Base mock spawner - + - disables user-switching that we need root permissions to do - spawns `jupyterhub.tests.mocksu` instead of a full single-user server """ def make_preexec_fn(self, *a, **kw): # skip the setuid stuff return - + def _set_user_changed(self, name, old, new): pass - + def user_env(self, env): + if self.handler: + env['HANDLER_ARGS'] = self.handler.request.query return env @default('cmd') diff --git a/jupyterhub/tests/mocksu.py b/jupyterhub/tests/mocksu.py index 817e823d..6c663cfa 100644 --- a/jupyterhub/tests/mocksu.py +++ b/jupyterhub/tests/mocksu.py @@ -27,13 +27,13 @@ class ArgsHandler(web.RequestHandler): self.write(json.dumps(sys.argv)) def main(args): - + app = web.Application([ (r'.*/args', ArgsHandler), (r'.*/env', EnvHandler), (r'.*', EchoHandler), ]) - + server = httpserver.HTTPServer(app) server.listen(args.port) try: @@ -45,4 +45,4 @@ if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('--port', type=int) args, extra = parser.parse_known_args() - main(args) \ No newline at end of file + main(args) diff --git a/jupyterhub/tests/test_api.py b/jupyterhub/tests/test_api.py index e68e5d04..4e8b1875 100644 --- a/jupyterhub/tests/test_api.py +++ b/jupyterhub/tests/test_api.py @@ -604,6 +604,32 @@ def test_spawn(app): assert app.users.count_active_users()['pending'] == 0 +@mark.gen_test +def test_spawn_handler(app): + """Test that the requesting Handler is passed to Spawner.handler""" + db = app.db + name = 'salmon' + user = add_user(db, app=app, name=name) + app_user = app.users[name] + + # spawn via API with ?foo=bar + r = yield api_request(app, 'users', name, 'server', method='post', params={'foo': 'bar'}) + r.raise_for_status() + + # verify that request params got passed down + # implemented in MockSpawner + url = public_url(app, user) + r = yield async_requests.get(ujoin(url, 'env')) + env = r.json() + assert 'HANDLER_ARGS' in env + assert env['HANDLER_ARGS'] == 'foo=bar' + # make user spawner.handler doesn't persist after spawn finishes + assert app_user.spawner.handler is None + + r = yield api_request(app, 'users', name, 'server', method='delete') + r.raise_for_status() + + @mark.slow @mark.gen_test def test_slow_spawn(app, no_patience, slow_spawn): diff --git a/jupyterhub/tests/test_pages.py b/jupyterhub/tests/test_pages.py index 18c91e0d..62a74106 100644 --- a/jupyterhub/tests/test_pages.py +++ b/jupyterhub/tests/test_pages.py @@ -168,6 +168,31 @@ def test_spawn_redirect(app): assert path == ujoin(app.base_url, '/user/%s/' % name) +@pytest.mark.gen_test +def test_spawn_handler_access(app): + name = 'winston' + cookies = yield app.login_user(name) + u = app.users[orm.User.find(app.db, name)] + + status = yield u.spawner.poll() + assert status is not None + + # spawn server via browser link with ?arg=value + r = yield get_page('spawn', app, cookies=cookies, params={'arg': 'value'}) + r.raise_for_status() + + # verify that request params got passed down + # implemented in MockSpawner + r = yield async_requests.get(ujoin(public_url(app, u), 'env')) + env = r.json() + assert 'HANDLER_ARGS' in env + assert env['HANDLER_ARGS'] == 'arg=value' + + # stop server + r = yield api_request(app, 'users', name, 'server', method='delete') + r.raise_for_status() + + @pytest.mark.gen_test def test_spawn_admin_access(app, admin_access): """GET /user/:name as admin with admin-access spawns user's server"""