import datetime import json import os import unittest import shutil from django.utils import timezone, six import django_react from django_react.render import render_component, RenderedComponent from django_react.bundle import ( get_webpack_config, get_var_from_path, get_component_config_filename, bundle_component ) from django_react.exceptions import ComponentRenderingError, ComponentSourceFileNotFound, ComponentWasNotBundled from django_webpack.compiler import WebpackBundle from django_react.conf import settings from .settings import STATIC_ROOT NODE_MODULES = os.path.join(os.path.dirname(django_react.__file__), 'services', 'node_modules') COMPONENT_ROOT = os.path.join(os.path.dirname(__file__), 'components') HELLO_WORLD_COMPONENT_JS = os.path.join(COMPONENT_ROOT, 'HelloWorld.js') HELLO_WORLD_COMPONENT_JSX = os.path.join(COMPONENT_ROOT, 'HelloWorld.jsx') HELLO_WORLD_WRAPPER_COMPONENT = os.path.join(COMPONENT_ROOT, 'HelloWorldWrapper.jsx') ERROR_THROWING_COMPONENT = os.path.join(COMPONENT_ROOT, 'ErrorThrowingComponent.jsx') SYNTAX_ERROR_COMPONENT = os.path.join(COMPONENT_ROOT, 'SyntaxErrorComponent.jsx') REACT_ADDONS_COMPONENT = os.path.join(COMPONENT_ROOT, 'ReactAddonsComponent.jsx') STATIC_FILE_FINDER_COMPONENT = 'test_app/StaticFileFinderComponent.jsx' class TestDjangoReact(unittest.TestCase): @classmethod def setUpClass(cls): # Ensure we have a clean slate for the run if os.path.exists(STATIC_ROOT): shutil.rmtree(STATIC_ROOT) @classmethod def tearDownClass(cls): # Ensure we leave a clean slate after the run if os.path.exists(STATIC_ROOT): shutil.rmtree(STATIC_ROOT) def test_can_render_a_component_in_js(self): component = render_component(HELLO_WORLD_COMPONENT_JS, to_static_markup=True) self.assertEqual(str(component), 'Hello ') def test_can_generate_a_var_from_a_path(self): self.assertEqual(get_var_from_path('/foo/bar/woz.jsx'), 'bar__woz') self.assertEqual(get_var_from_path('/foo-bar/woz.jsx'), 'foo_bar__woz') self.assertEqual(get_var_from_path('/foo/ba +\\r/woz.jsx'), 'ba_r__woz') self.assertEqual(get_var_from_path('foo/test/one/two/bar/a'), 'bar__a') self.assertEqual(get_var_from_path('foo/test/one/two/bar/.a'), 'bar___a') "\nvar resolve = require('/Users/markfinger/Projects/django-react/django_react/services/node_modules/resolve');\n\nmodule.exports = {\n context: '/Users/markfinger/Projects/django-react/tests/components',\n entry: './HelloWorld.js',\n output: {\n path: '[bundle_dir]/react-components',\n filename: 'components__HelloWorld-[hash].js',\n libraryTarget: 'umd',\n library: 'components__HelloWorld'\n },\n externals: [{\n react: {\n commonjs2: resolve.sync('react', {basedir: '/Users/markfinger/Projects/django-react/tests/components'}),\n root: 'React'\n },\n 'react/addons': {\n commonjs2: resolve.sync('react/addons', {basedir: '/Users/markfinger/Projects/django-react/tests/components'}),\n root: 'React'\n }\n }]\n};\n" "\nvar resolve = require('/Users/markfinger/Projects/django-react/django_react/services/node_modules/resolve');\n\nmodule.exports = {\n context: '/Users/markfinger/Projects/django-react/tests/components',\n entry: './HelloWorld.js',\n output: {\n path: '[bundle_dir]/react-components',\n filename: 'components__HelloWorld-[hash].js',\n libraryTarget: 'umd',\n library: 'components__HelloWorld'\n },\n externals: [{\n react: {\n commonjs2: resolve.sync('react', {basedir: '/Users/markfinger/Projects/django-react/tests/components'}),\n root: 'React'\n },\n 'react/addons': {\n commonjs2: resolve.sync('react/addons', {basedir: '/Users/markfinger/Projects/django-react/tests/components'}),\n root: 'React'\n }\n }],\n devtool: 'eval'\n};\n" def test_can_generate_a_webpack_config_for_a_js_component(self): _DEV_TOOL = settings.DEV_TOOL settings._unlock() settings.DEV_TOOL = True config = get_webpack_config(HELLO_WORLD_COMPONENT_JS) expected = \ """ var resolve = require('%s'); module.exports = { context: '%s', entry: './HelloWorld.js', output: { path: '[bundle_dir]/react-components', filename: 'components__HelloWorld-[hash].js', libraryTarget: 'umd', library: 'components__HelloWorld' }, externals: [{ react: { commonjs2: resolve.sync('react', {basedir: '%s'}), root: 'React' }, 'react/addons': { commonjs2: resolve.sync('react/addons', {basedir: '%s'}), root: 'React' } }], devtool: 'eval' }; """ % ( os.path.join(NODE_MODULES, 'resolve'), COMPONENT_ROOT, COMPONENT_ROOT, COMPONENT_ROOT, ) self.assertEqual(config, expected) settings.DEV_TOOL = _DEV_TOOL settings._lock() "\nvar resolve = require('/Users/markfinger/Projects/django-react/django_react/services/node_modules/resolve');\n\nmodule.exports = {\n context: '/Users/markfinger/Projects/django-react/tests/components',\n entry: './HelloWorld.jsx',\n output: {\n path: '[bundle_dir]/react-components',\n filename: 'components__HelloWorld-[hash].js',\n libraryTarget: 'umd',\n library: 'components__HelloWorld'\n },\n externals: [{\n react: {\n commonjs2: resolve.sync('react', {basedir: '/Users/markfinger/Projects/django-react/tests/components'}),\n root: 'React'\n },\n 'react/addons': {\n commonjs2: resolve.sync('react/addons', {basedir: '/Users/markfinger/Projects/django-react/tests/components'}),\n root: 'React'\n }\n }],\n devtool: 'eval'\n,\n module: {\n loaders: [{\n test: /\\.jsx$/,\n exclude: /node_modules/,\n loader: 'babel-loader'\n }]\n },\n resolveLoader: {\n root: '/Users/markfinger/Projects/django-react/django_react/services/node_modules'\n }\n\n};\n" "\nvar resolve = require('/Users/markfinger/Projects/django-react/django_react/services/node_modules/resolve');\n\nmodule.exports = {\n context: '/Users/markfinger/Projects/django-react/tests/components',\n entry: './HelloWorld.jsx',\n output: {\n path: '[bundle_dir]/react-components',\n filename: 'components__HelloWorld-[hash].js',\n libraryTarget: 'umd',\n library: 'components__HelloWorld'\n },\n externals: [{\n react: {\n commonjs2: resolve.sync('react', {basedir: '/Users/markfinger/Projects/django-react/tests/components'}),\n root: 'React'\n },\n 'react/addons': {\n commonjs2: resolve.sync('react/addons', {basedir: '/Users/markfinger/Projects/django-react/tests/components'}),\n root: 'React'\n }\n }],\n devtool: 'eval',\n\n module: {\n loaders: [{\n test: /\\.jsx$/,\n exclude: /node_modules/,\n loader: 'babel-loader'\n }]\n },\n resolveLoader: {\n root: '/Users/markfinger/Projects/django-react/django_react/services/node_modules'\n }\n\n};\n" def test_can_generate_a_webpack_config_for_a_jsx_component(self): _DEV_TOOL = settings.DEV_TOOL settings._unlock() settings.DEV_TOOL = True config = get_webpack_config(HELLO_WORLD_COMPONENT_JSX, translate=True) expected = \ """ var resolve = require('%s'); module.exports = { context: '%s', entry: './HelloWorld.jsx', output: { path: '[bundle_dir]/react-components', filename: 'components__HelloWorld-[hash].js', libraryTarget: 'umd', library: 'components__HelloWorld' }, externals: [{ react: { commonjs2: resolve.sync('react', {basedir: '%s'}), root: 'React' }, 'react/addons': { commonjs2: resolve.sync('react/addons', {basedir: '%s'}), root: 'React' } }], devtool: 'eval', module: { loaders: [{ test: /\.jsx$/, exclude: /node_modules/, loader: 'babel-loader' }] }, resolveLoader: { root: '%s' } }; """ % ( os.path.join(NODE_MODULES, 'resolve'), COMPONENT_ROOT, COMPONENT_ROOT, COMPONENT_ROOT, NODE_MODULES, ) self.assertEqual(config, expected) settings.DEV_TOOL = _DEV_TOOL settings._lock() def test_can_generate_and_create_a_config_file(self): filename = get_component_config_filename(HELLO_WORLD_COMPONENT_JS) with open(filename, 'r') as config_file: contents = config_file.read() self.assertEqual(contents, get_webpack_config(HELLO_WORLD_COMPONENT_JS)) filename = get_component_config_filename(HELLO_WORLD_COMPONENT_JSX, translate=True) with open(filename, 'r') as config_file: contents = config_file.read() self.assertEqual(contents, get_webpack_config(HELLO_WORLD_COMPONENT_JSX, translate=True)) def test_generated_config_files_are_cached(self): self.assertEqual( get_component_config_filename(HELLO_WORLD_COMPONENT_JS), get_component_config_filename(HELLO_WORLD_COMPONENT_JS), ) self.assertEqual( get_component_config_filename(HELLO_WORLD_COMPONENT_JS, translate=True), get_component_config_filename(HELLO_WORLD_COMPONENT_JS, translate=True), ) self.assertNotEqual( get_component_config_filename(HELLO_WORLD_COMPONENT_JS, translate=True), get_component_config_filename(HELLO_WORLD_COMPONENT_JS, translate=False), ) self.assertNotEqual( get_component_config_filename(HELLO_WORLD_COMPONENT_JS), get_component_config_filename(HELLO_WORLD_COMPONENT_JSX), ) self.assertNotEqual( get_component_config_filename(HELLO_WORLD_COMPONENT_JS, translate=True), get_component_config_filename(HELLO_WORLD_COMPONENT_JSX, translate=True), ) self.assertNotEqual( get_component_config_filename(HELLO_WORLD_COMPONENT_JS, translate=True), get_component_config_filename(HELLO_WORLD_COMPONENT_JSX, translate=False), ) self.assertNotEqual( get_component_config_filename(HELLO_WORLD_COMPONENT_JS, translate=False), get_component_config_filename(HELLO_WORLD_COMPONENT_JSX, translate=False), ) def test_can_bundle_a_js_component(self): bundle = bundle_component(HELLO_WORLD_COMPONENT_JS) asset = bundle.get_assets()[0] self.assertTrue(os.path.exists(asset['path'])) with open(asset['path'], 'r') as asset_file: contents = asset_file.read() self.assertIn('// __DJANGO_WEBPACK_BUNDLE_TEST__', contents) def test_can_bundle_a_jsx_component(self): bundle = bundle_component(HELLO_WORLD_COMPONENT_JSX, translate=True) asset = bundle.get_assets()[0] self.assertTrue(os.path.exists(asset['path'])) with open(asset['path'], 'r') as asset_file: contents = asset_file.read() self.assertIn('// __DJANGO_WEBPACK_TRANSLATE_BUNDLE_TEST__', contents) def test_can_render_a_bundled_js_component(self): bundle = bundle_component(HELLO_WORLD_COMPONENT_JS) asset = bundle.get_assets()[0] component = render_component(asset['path'], to_static_markup=True) self.assertEqual(str(component), 'Hello ') def test_can_render_a_bundled_jsx_component(self): bundle = bundle_component(HELLO_WORLD_COMPONENT_JSX, translate=True) asset = bundle.get_assets()[0] component = render_component(asset['path'], to_static_markup=True) self.assertEqual(str(component), 'Hello ') def test_can_pass_props_when_rendering_a_bundled_js_component(self): bundle = bundle_component(HELLO_WORLD_COMPONENT_JS) asset = bundle.get_assets()[0] component = render_component(asset['path'], props={'name': 'world!'}, to_static_markup=True) self.assertEqual(str(component), 'Hello world!') def test_can_pass_props_when_rendering_a_bundled_jsx_component(self): bundle = bundle_component(HELLO_WORLD_COMPONENT_JSX, translate=True) asset = bundle.get_assets()[0] component = render_component(asset['path'], props={'name': 'world!'}, to_static_markup=True) self.assertEqual( str(component), 'Hello world!' ) def test_can_render_a_component_in_jsx(self): component = render_component(HELLO_WORLD_COMPONENT_JSX, translate=True, to_static_markup=True) self.assertEqual(str(component), 'Hello ') def test_can_render_a_component_requiring_another_component(self): component = render_component( HELLO_WORLD_WRAPPER_COMPONENT, props={ 'name': 'world!', 'numbers': [1, 2, 3, 4, 5], }, translate=True, to_static_markup=True ) self.assertEqual(str(component), '