Просмотр исходного кода

Updated tests, added downgrade option

djsilcock 8 лет назад
Родитель
Сommit
3b09af943c
2 измененных файлов с 100 добавлено и 10 удалено
  1. 14 1
      flaskbb/cli/plugins.py
  2. 86 9
      tests/cli/test_plugins.py

+ 14 - 1
flaskbb/cli/plugins.py

@@ -45,7 +45,7 @@ def new_plugin(plugin_identifier, template):
     It will either accept a valid path on the filesystem
     or a URL to a Git repository which contains the cookiecutter template.
     """
-    out_dir = os.path.join(current_app.root_path, "plugins")
+    out_dir = current_app.extensions['plugin_manager'].plugin_folder  #monkeypatched by test routine
     click.secho("[+] Creating new plugin...",
                 fg="cyan")
     cookiecutter(template, output_dir=out_dir)
@@ -155,3 +155,16 @@ def upgrade_plugin(plugin_identifier):
         plugin.upgrade_database()
     except AttributeError:
         pass
+
+@plugins.command("downgrade")
+@click.argument("plugin_identifier")
+def downgrade_plugin(plugin_identifier):
+    """Downgrades database to remove a plugin's models"""
+    validate_plugin(plugin_identifier)
+    plugin = get_plugin_from_all(plugin_identifier)
+    if click.confirm("Please confirm you want to remove this plugins data from the database"):
+        click.secho("[+] Downgrading plugin {}...".format(plugin.name), fg="cyan")
+        try:
+            plugin.downgrade_database()
+        except AttributeError:
+            pass

+ 86 - 9
tests/cli/test_plugins.py

@@ -1,31 +1,108 @@
 
-import click
-import zipfile,urllib,os
+import click,pytest
+import zipfile,urllib,os,shutil
 from click.testing import CliRunner
 from flaskbb.cli import main as cli_main
-
+from flaskbb import plugins
+from flaskbb.extensions import db
+from importlib import import_module
 def test_new_plugin(tmpdir,application,monkeypatch):
     runner=CliRunner()
+    #download the cookiecutter file to use locally (bypasses prompt about re-cloning)
     zipfilename=str(tmpdir.join('cookiecutter.zip'))
-    monkeypatch.setattr(cli_main,'create_app',lambda s: application)
-    urllib.urlretrieve('https://github.com/sh4nks/cookiecutter-flaskbb-plugin/archive/master.zip',zipfilename)
+    urllib.urlretrieve('https://github.com/sh4nks/cookiecutter-flaskbb-plugin/archive/master.zip', zipfilename)
     with zipfile.ZipFile(zipfilename) as zf:
         zf.extractall(str(tmpdir))
-    cookiecutterpath=tmpdir.join('cookiecutter-flaskbb-plugin-master')
+    cookiecutterpath = tmpdir.join('cookiecutter-flaskbb-plugin-master')
+
+    tmp_plugin_folder=str(tmpdir.join('plugin_folder'))
+    os.mkdir(tmp_plugin_folder)
+    monkeypatch.setattr(cli_main,'create_app',lambda s: application)
+    monkeypatch.setattr(application.extensions['plugin_manager'],'plugin_folder',tmp_plugin_folder)
     input='\n'.join([
     'Test Name',
     'someone@nowhere.com',
     'Testing Plugin',
     '',
-    '',
+    'TestingPlugin',
     'Straightforward Test Plugin',
     'www.example.com',
     '1.0.0'])
 
+
     result=runner.invoke(cli_main.flaskbb,['plugins','new','testplugin','--template',str(cookiecutterpath)],input=input)
     assert result.exit_code == 0
-    plugin_dir = os.join(application.extensions['plugin_manager'].plugin_folder, 'testing_plugin')
+    plugin_dir = os.path.join(application.extensions['plugin_manager'].plugin_folder, 'testing_plugin')
     assert os.path.exists(plugin_dir)
     assert os.path.isdir(plugin_dir)
-    assert __import__('flaskbb.plugins.testing_plugin').__plugin__=='TestingPlugin'
+    #add the temporary folder to the plugins path so import flaskbb.plugins.test_plugin works as expected
+    monkeypatch.setattr(plugins,'__path__',plugins.__path__+[tmp_plugin_folder])
+    assert import_module('flaskbb.plugins.testing_plugin').__plugin__=='TestingPlugin'
+
+def test_migrate_plugin(tmpdir,monkeypatch,application):
+
+    pluginmanager = application.extensions['plugin_manager']
+    orig_plugin_folder=pluginmanager.plugin_folder
+    tmp_plugin_folder = str(tmpdir.join('plugin_folder'))
+    os.mkdir(tmp_plugin_folder)
+    shutil.copytree(os.path.join(orig_plugin_folder,'_migration_environment'),os.path.join(tmp_plugin_folder,'_migration_environment'))
+    os.mkdir(os.path.join(tmp_plugin_folder,'testplugin'))
+    with open(os.path.join(tmp_plugin_folder,'testplugin','__init__.py'),'w') as pyfile:
+        pyfile.write('\r\n'.join([
+        "from flaskbb.plugins import FlaskBBPlugin",
+        "from flaskbb.extensions import db",
+        "class TestPlugin(FlaskBBPlugin):",
+        "    settings_key='testplugin'",
+        "    def somequery(self):",
+        "        TestModel.query.all()",
+        "class TestModel(db.Model):",
+        "    __tablename__='testtable'",
+        "    testkey=db.Column(db.Integer,primary_key=True)",
+        "",
+        "__plugin__='TestPlugin'",
+        ]))
+    import json
+    jsoninfo={
+        "identifier": "testplugin",
+        "name": "TestPlugin",
+        "author": "sh4nks",
+        "website": "http://flaskbb.org",
+        "license": "BSD",
+        "description": "A Test Plugin for FlaskBB",
+        "version": "0.1"
+    }
+    with open(os.path.join(tmp_plugin_folder,'testplugin','info.json'),'w') as jsonfile:
+        json.dump(jsoninfo,jsonfile)
+
+
+    monkeypatch.setattr(cli_main, 'create_app', lambda s: application)
+
+    monkeypatch.setattr(pluginmanager, 'plugin_folder', tmp_plugin_folder)
+    # add the temporary folder to the plugins path so import flaskbb.plugins.test_plugin works as expected
+    monkeypatch.setattr(plugins, '__path__', plugins.__path__ + [tmp_plugin_folder])
+    pluginmanager._plugins=None
+    pluginmanager._all_plugins = None
+    pluginmanager._available_plugins = dict()
+    pluginmanager._found_plugins = dict()
+    pluginmanager.setup_plugins()
+    assert 'testplugin' in pluginmanager.plugins
+    versionsdir=os.path.join(tmp_plugin_folder,'testplugin','migration_versions')
+    assert not os.path.exists(versionsdir)
+    testplugin=pluginmanager.plugins['testplugin']
+    with application.app_context():
+        testplugin.migrate()
+        assert os.path.exists(versionsdir)
+        dirlist = os.listdir(versionsdir)
+        assert dirlist
+        dirlist=[os.path.join(versionsdir,d) for d in dirlist if d.endswith('.py')]
+        for d in dirlist:
+            with open(d,'r') as f:
+                output='\n'.join([l for l in f])
+
+        assert 'testtable' in output
+        with pytest.raises(Exception,message='Should not be able to run migrations twice'):
+             testplugin.migrate()
+        with pytest.raises(Exception,message='Operations should fail as model not yet registered'):
+             testplugin.somequery()
+        testplugin.upgrade_database()