test_plugins.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. import zipfile
  2. import urllib
  3. import os
  4. import shutil
  5. import json
  6. import pytest
  7. from click.testing import CliRunner
  8. from flaskbb.cli import main as cli_main
  9. from flaskbb import plugins
  10. from importlib import import_module
  11. def test_new_plugin(tmpdir, application, monkeypatch):
  12. runner = CliRunner()
  13. # download the cookiecutter file to use locally
  14. # (bypasses prompt about re-cloning)
  15. zipfilename = str(tmpdir.join('cookiecutter.zip'))
  16. urllib.urlretrieve('https://github.com/sh4nks/cookiecutter-flaskbb-plugin/archive/master.zip', zipfilename) # noqa
  17. with zipfile.ZipFile(zipfilename) as zf:
  18. zf.extractall(str(tmpdir))
  19. cookiecutterpath = tmpdir.join('cookiecutter-flaskbb-plugin-master')
  20. tmp_plugin_folder = str(tmpdir.join('plugin_folder'))
  21. os.mkdir(tmp_plugin_folder)
  22. monkeypatch.setattr(cli_main, 'create_app', lambda s: application)
  23. monkeypatch.setattr(application.extensions['plugin_manager'],
  24. 'plugin_folder', tmp_plugin_folder)
  25. stdin = '\n'.join([
  26. 'Test Name',
  27. 'someone@nowhere.com',
  28. 'Testing Plugin',
  29. '',
  30. 'TestingPlugin',
  31. 'Straightforward Test Plugin',
  32. 'www.example.com',
  33. '1.0.0'
  34. ])
  35. result = runner.invoke(
  36. cli_main.flaskbb,
  37. ['plugins', 'new', 'testplugin', '--template', str(cookiecutterpath)],
  38. input=stdin
  39. )
  40. assert result.exit_code == 0
  41. plugin_dir = os.path.join(
  42. application.extensions['plugin_manager'].plugin_folder,
  43. 'testing_plugin'
  44. )
  45. assert os.path.exists(plugin_dir)
  46. assert os.path.isdir(plugin_dir)
  47. # add the temporary folder to the plugins path
  48. # so import flaskbb.plugins.test_plugin works as expected
  49. monkeypatch.setattr(
  50. plugins, '__path__', plugins.__path__ + [tmp_plugin_folder]
  51. )
  52. assert import_module('flaskbb.plugins.testing_plugin').__plugin__ == 'TestingPlugin' # noqa
  53. def test_migrate_plugin(tmpdir, monkeypatch, application):
  54. pluginmanager = application.extensions['plugin_manager']
  55. orig_plugin_folder = pluginmanager.plugin_folder
  56. tmp_plugin_folder = str(tmpdir.join('plugin_folder'))
  57. os.mkdir(tmp_plugin_folder)
  58. shutil.copytree(
  59. os.path.join(orig_plugin_folder, '_migration_environment'),
  60. os.path.join(tmp_plugin_folder, '_migration_environment')
  61. )
  62. os.mkdir(os.path.join(tmp_plugin_folder, 'testplugin'))
  63. pyfile = os.path.join(tmp_plugin_folder, 'testplugin', '__init__.py')
  64. with open(pyfile, 'w') as pyfile:
  65. pyfile.write('\r\n'.join([
  66. "from flaskbb.plugins import FlaskBBPlugin",
  67. "from flaskbb.extensions import db",
  68. "class TestPlugin(FlaskBBPlugin):",
  69. " settings_key='testplugin'",
  70. " def somequery(self):",
  71. " TestModel.query.all()",
  72. "class TestModel(db.Model):",
  73. " __tablename__='testtable'",
  74. " testkey=db.Column(db.Integer,primary_key=True)",
  75. "",
  76. "__plugin__='TestPlugin'",
  77. ]))
  78. jsoninfo = {
  79. "identifier": "testplugin",
  80. "name": "TestPlugin",
  81. "author": "sh4nks",
  82. "website": "http://flaskbb.org",
  83. "license": "BSD",
  84. "description": "A Test Plugin for FlaskBB",
  85. "version": "0.1"
  86. }
  87. jsonfile = os.path.join(tmp_plugin_folder, 'testplugin', 'info.json')
  88. with open(jsonfile, 'w') as jsonfile:
  89. json.dump(jsoninfo, jsonfile)
  90. monkeypatch.setattr(cli_main, 'create_app', lambda s: application)
  91. monkeypatch.setattr(pluginmanager, 'plugin_folder', tmp_plugin_folder)
  92. # add the temporary folder to the plugins path
  93. # so import flaskbb.plugins.test_plugin works as expected
  94. monkeypatch.setattr(
  95. plugins, '__path__', plugins.__path__ + [tmp_plugin_folder]
  96. )
  97. pluginmanager._plugins = None
  98. pluginmanager._all_plugins = None
  99. pluginmanager._available_plugins = dict()
  100. pluginmanager._found_plugins = dict()
  101. pluginmanager.setup_plugins()
  102. assert 'testplugin' in pluginmanager.plugins
  103. versionsdir = os.path.join(
  104. tmp_plugin_folder, 'testplugin', 'migration_versions'
  105. )
  106. assert not os.path.exists(versionsdir)
  107. testplugin = pluginmanager.plugins['testplugin']
  108. with application.app_context():
  109. testplugin.migrate()
  110. assert os.path.exists(versionsdir)
  111. dirlist = os.listdir(versionsdir)
  112. assert dirlist
  113. dirlist = [os.path.join(versionsdir, d)
  114. for d in dirlist if d.endswith('.py')]
  115. for d in dirlist:
  116. with open(d, 'r') as f:
  117. output = '\n'.join([l for l in f])
  118. assert 'testtable' in output
  119. exception_msg = 'Should not be able to run migrations twice'
  120. with pytest.raises(Exception, message=exception_msg):
  121. testplugin.migrate()
  122. exception_msg = "Operations should fail as model not yet registered"
  123. with pytest.raises(Exception, message=exception_msg):
  124. testplugin.somequery()
  125. testplugin.upgrade_database()