diff --git a/spec/require.spec.js b/spec/require.spec.js index fdba9e2..17e072c 100644 --- a/spec/require.spec.js +++ b/spec/require.spec.js @@ -62,6 +62,14 @@ describe("Require.js module register method test", function() { expect(lib.require('foo')).toEqual('FOO'); }); + it("with AMD define object", function() { + lib.register("foo-static", function (define, require, module, exports) { + define([], {foo: 1}); + }); + + expect(lib.require('foo-static')).toEqual({foo: 1}); + }); + it("with AMD define and reserved requirements", function() { lib.register("amd_define/foo", function (define, require, module, exports) { define([], function () { diff --git a/src/Bundler/Pipeline/ContentPipeline.php b/src/Bundler/Pipeline/ContentPipeline.php index 8f69d3c..29cde01 100644 --- a/src/Bundler/Pipeline/ContentPipeline.php +++ b/src/Bundler/Pipeline/ContentPipeline.php @@ -94,7 +94,7 @@ public function push(array $dependencies, ReaderInterface $file_reader, File $ta $module_name = $file->getName(); if (!empty($this->config->getSourceRoot()) - && false !== strpos($module_name, $this->config->getSourceRoot()) + && 0 === strpos($module_name, $this->config->getSourceRoot()) ) { $chopped = substr($file->dir, strlen($this->config->getSourceRoot())); $base_dir = $chopped ? trim($chopped, '/') : ''; diff --git a/src/Bundler/Processor/ModuleProcessor.php b/src/Bundler/Processor/ModuleProcessor.php index 9a2645b..0948b77 100644 --- a/src/Bundler/Processor/ModuleProcessor.php +++ b/src/Bundler/Processor/ModuleProcessor.php @@ -26,7 +26,9 @@ public function peek(string $cwd, ContentState $state): void public function transpile(string $cwd, ContentItem $item): void { - $js = "register('" . $item->module_name . "', function (define, require, module, exports) {\n"; + $js = "register(" + . json_encode($item->module_name, JSON_UNESCAPED_SLASHES) + . ", function (define, require, module, exports) {\n"; $js .= $item->getContent(); $js .= "\n});\n"; diff --git a/src/Bundler/Processor/TsContentProcessor.php b/src/Bundler/Processor/TsContentProcessor.php index f7e6d1d..0503305 100644 --- a/src/Bundler/Processor/TsContentProcessor.php +++ b/src/Bundler/Processor/TsContentProcessor.php @@ -35,9 +35,7 @@ public function transpile(string $cwd, ContentItem $item): void { $module_name = $item->module_name; - if (false !== ($i = strrpos($module_name, '.'))) { - $module_name = substr($module_name, 0, $i); - } + $module_name = preg_replace('/\.ts$/i', '', $module_name); $item->transition( ContentState::PROCESSED, diff --git a/src/Bundler/Runner/js/tsc.js b/src/Bundler/Runner/js/tsc.js index b69809a..1174425 100644 --- a/src/Bundler/Runner/js/tsc.js +++ b/src/Bundler/Runner/js/tsc.js @@ -5,9 +5,11 @@ function compile(source) { compilerOptions: { inlineSourceMap: false, skipLibCheck: true, + importHelpers: true, target: ts.ScriptTarget.ES5, module: ts.ModuleKind.CommonJS, moduleResolution: ts.ModuleResolutionKind.NodeJs, + emitDecoratorMetadata: true, experimentalDecorators: true } }); diff --git a/src/Config/FileConfig.php b/src/Config/FileConfig.php index 1fec758..0b2e4c9 100644 --- a/src/Config/FileConfig.php +++ b/src/Config/FileConfig.php @@ -34,16 +34,21 @@ final class FileConfig implements ConfigInterface * @param bool $dev * @param EventDispatcherInterface $dispatcher * @param LoggerInterface $logger + * @param mixed[] $non_static_options */ public function __construct( string $config_file, array $plugins = [], bool $dev = false, EventDispatcherInterface $dispatcher = null, - LoggerInterface $logger = null + LoggerInterface $logger = null, + array $non_static_options = [] ) { $this->config_file = $config_file; - $this->config_file_contents = json_decode(file_get_contents($this->config_file), true); + $this->config_file_contents = array_merge( + json_decode(file_get_contents($this->config_file), true), + $non_static_options + ); $this->dispatcher = $dispatcher ?? new EventDispatcher(); $this->logger = $logger ?? new NullLogger(); $this->plugins = $plugins; @@ -123,7 +128,6 @@ public function getOutputFolder(bool $include_public_folder = true): string if (! $include_public_folder) { return $output_folder; } - $web_root = $this->config_file_contents['web-root']; return rtrim($web_root, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $output_folder; } diff --git a/src/Event/AssetEvents.php b/src/Event/AssetEvents.php index 4580e3f..278bae8 100644 --- a/src/Event/AssetEvents.php +++ b/src/Event/AssetEvents.php @@ -37,4 +37,10 @@ final class AssetEvents * @var string */ public const READY = 'asset.ready'; + + /** + * Used to find the source of an asset. Can be used for example with the AngularPlugin to find stylesheets of an + * Angular component and instructing to use a less file instead. + */ + public const FIND_SOURCE = 'asset.find_source'; } diff --git a/src/Event/FindSourceEvent.php b/src/Event/FindSourceEvent.php new file mode 100644 index 0000000..7866f6c --- /dev/null +++ b/src/Event/FindSourceEvent.php @@ -0,0 +1,29 @@ +file_path = $file_path; + } + + public function getFilepath(): string + { + return $this->file_path; + } + + public function setFilepath(string $file_path): void + { + $this->file_path = $file_path; + } +} diff --git a/src/EventListener/AngularHtmlListener.php b/src/EventListener/AngularHtmlListener.php index f84deb7..ce0fd18 100644 --- a/src/EventListener/AngularHtmlListener.php +++ b/src/EventListener/AngularHtmlListener.php @@ -7,6 +7,8 @@ use Hostnet\Component\Resolver\Bundler\Asset; use Hostnet\Component\Resolver\Event\AssetEvent; +use Hostnet\Component\Resolver\Event\AssetEvents; +use Hostnet\Component\Resolver\Event\FindSourceEvent; use Hostnet\Component\Resolver\File; use Hostnet\Component\Resolver\FileSystem\FileReader; use Hostnet\Component\Resolver\FileSystem\ReaderInterface; @@ -79,12 +81,16 @@ function ($match) use ($file, $reader) { */ private function getCompiledAssetFor(string $linked_file, File $owning_file, ReaderInterface $reader): string { - $file_path = $linked_file; - - if ($file_path[0] === '.' && $owning_file->dir !== '.' && !empty($owning_file->dir)) { - $file_path = $owning_file->dir . '/' . $file_path; + if (substr($linked_file, 1, 0) === '/') { + $file_path = $linked_file; + } else { + $file_path = $owning_file->dir . '/' . $linked_file; } + $event = new FindSourceEvent($file_path); + $this->plugin_api->getConfig()->getEventDispatcher()->dispatch(AssetEvents::FIND_SOURCE, $event); + $file_path = $event->getFilepath(); + $target_file = new File(File::clean($file_path)); $pipeline = $this->plugin_api->getPipeline(); $asset = new Asset($this->plugin_api->getFinder()->all($target_file), $pipeline->peek($target_file)); diff --git a/src/Import/BuiltIn/AngularImportCollector.php b/src/Import/BuiltIn/AngularImportCollector.php index 68fca14..457f39c 100644 --- a/src/Import/BuiltIn/AngularImportCollector.php +++ b/src/Import/BuiltIn/AngularImportCollector.php @@ -6,16 +6,25 @@ namespace Hostnet\Component\Resolver\Import\BuiltIn; +use Hostnet\Component\Resolver\Event\AssetEvents; +use Hostnet\Component\Resolver\Event\FindSourceEvent; use Hostnet\Component\Resolver\File; use Hostnet\Component\Resolver\Import\Import; use Hostnet\Component\Resolver\Import\ImportCollection; use Hostnet\Component\Resolver\Import\ImportCollectorInterface; +use Hostnet\Component\Resolver\Plugin\PluginApi; /** * Angular asset resolver. */ final class AngularImportCollector implements ImportCollectorInterface { + private $plugin_api; + + public function __construct(PluginApi $plugin_api) + { + $this->plugin_api = $plugin_api; + } /** * {@inheritdoc} */ @@ -33,25 +42,20 @@ public function collect(string $cwd, File $file, ImportCollection $imports): voi if (preg_match_all('/templateUrl\s*:(\s*[\'"`](.*?)[\'"`]\s*)/m', $content, $matches) > 0) { foreach ($matches[2] as $match) { - $file_path = $match; - - if ($file_path[0] === '.') { - $file_path = $file->dir . substr($file_path, 1); - } - + $file_path = File::clean($file->dir . '/' . $match); $imports->addImport(new Import($file_path, new File($file_path), true)); } } - if (preg_match_all('/styleUrls *:(\s*\[[^\]]*?\])/', $content, $matches) > 0) { + if (preg_match_all('/styleUrls\s*:(\s*\[[^\]]*?\])/', $content, $matches) > 0) { foreach ($matches[1] as $match) { if (preg_match_all('/([\'`"])((?:[^\\\\]\\\\\1|.)*?)\1/', $match, $inner_matches) > 0) { foreach ($inner_matches[2] as $inner_match) { - $file_path = $inner_match; - - if ($file_path[0] === '.') { - $file_path = $file->dir . substr($file_path, 1); - } - + $event = new FindSourceEvent($file->dir . '/./' . $inner_match); + $this->plugin_api->getConfig()->getEventDispatcher()->dispatch( + AssetEvents::FIND_SOURCE, + $event + ); + $file_path = File::clean($event->getFilepath()); $imports->addImport(new Import($file_path, new File($file_path), true)); } } diff --git a/src/Import/BuiltIn/JsImportCollector.php b/src/Import/BuiltIn/JsImportCollector.php index 8244849..cdf7272 100644 --- a/src/Import/BuiltIn/JsImportCollector.php +++ b/src/Import/BuiltIn/JsImportCollector.php @@ -37,6 +37,10 @@ public function supports(File $file): bool public function collect(string $cwd, File $file, ImportCollection $imports): void { $content = file_get_contents(File::makeAbsolutePath($file->path, $cwd)); + // remove contents if applicable so we do not find require statements inside commented code. + // that way the only accidental require statements we find are the one we find in if statements + // or between try { .. } catch. + $content = preg_replace('#\\/\\*([^*]|[\\r\\n]|(\\*+([^*/]|[\\r\\n])))*\\*+\\/#', '', $content) ? : $content; $n = preg_match_all('/(.?)require\(([\']([^\']+)[\']|["]([^"]+)["])\)/', $content, $matches); for ($i = 0; $i < $n; $i++) { diff --git a/src/Import/BuiltIn/TsImportCollector.php b/src/Import/BuiltIn/TsImportCollector.php index e48987a..82b20b5 100644 --- a/src/Import/BuiltIn/TsImportCollector.php +++ b/src/Import/BuiltIn/TsImportCollector.php @@ -40,22 +40,13 @@ public function collect(string $cwd, File $file, ImportCollection $imports): voi { $content = file_get_contents(File::makeAbsolutePath($file->path, $cwd)); $n = preg_match_all('/import([^;\'"]*from)?\s+["\'](.*?)["\'];/', $content, $matches); - $this->js_import_collector->collect($cwd, $file, $imports); for ($i = 0; $i < $n; $i++) { $path = $matches[2][$i]; try { - $import = $this->nodejs_resolver->asRequire($path, $file); - $base_name = basename($import->getImportedFile()->path); - - $ext = substr($base_name, strpos($base_name, '.')); - - if ($ext === '.d.ts') { - continue; - } - + $import = $this->nodejs_resolver->asRequire($path, $file); $imports->addImport($import); } catch (\RuntimeException $e) { continue; diff --git a/src/Import/Nodejs/FileResolver.php b/src/Import/Nodejs/FileResolver.php index ef5ff58..1cf8885 100644 --- a/src/Import/Nodejs/FileResolver.php +++ b/src/Import/Nodejs/FileResolver.php @@ -23,6 +23,13 @@ final class FileResolver implements FileResolverInterface { private $config; private $extensions; + /** + * Caching properties. Required since file IO is slow and finding the same resource again and again is slow. + */ + private $as_module = []; + private $as_file = []; + private $as_index = []; + private $as_dir = []; /** * @param ConfigInterface $config @@ -31,7 +38,11 @@ final class FileResolver implements FileResolverInterface public function __construct(ConfigInterface $config, array $extensions) { $this->config = $config; - $this->extensions = $extensions; + $this->extensions = array_map(function (string $extension) { + + + return '.' . ltrim($extension, '.'); + }, $extensions); } /** @@ -89,11 +100,17 @@ public function asRequire(string $name, File $parent): Import */ private function asFile(string $name): string { + if (isset($this->as_file[$name])) { + if ($this->as_file[$name] === false) { + throw new FileNotFoundException(sprintf('File %s could not be be found!', $name)); + } + return $this->as_file[$name]; + } $path = File::makeAbsolutePath($name, $this->config->getProjectRoot()); // 1. If X is a file, load X as JavaScript text. STOP if (is_file($path)) { - return File::clean($name); + return $this->as_file[$name] = File::clean($name); } // 2, If X.js is a file, load X.js as JavaScript text. STOP @@ -101,10 +118,11 @@ private function asFile(string $name): string // 4. If X.node is a file, load X.node as binary addon. STOP foreach ($this->extensions as $ext) { if (is_file($path . $ext)) { - return File::clean($name . $ext); + return $this->as_file[$name] = File::clean($name . $ext); } } + $this->as_file[$name] = false; throw new FileNotFoundException(sprintf('File %s could not be be found!', $name)); } @@ -117,21 +135,22 @@ private function asFile(string $name): string */ private function asIndex(string $name): string { + if (isset($this->as_index[$name])) { + if ($this->as_index[$name] === false) { + throw new FileNotFoundException(sprintf('File %s could not be be found!', $name)); + } + return $this->as_index[$name]; + } + $path = File::makeAbsolutePath($name, $this->config->getProjectRoot()); - // 1. If X/index.js is a file, load X/index.js as JavaScript text. STOP - if (is_file($path . '/index.js')) { - return File::clean($name . '/index.js'); - } - // 2. If X/index.json is a file, parse X/index.json to a JavaScript object. STOP - if (is_file($path . '/index.json')) { - return File::clean($name . '/index.json'); - } - // 3. If X/index.node is a file, load X/index.node as binary addon. STOP - if (is_file($path . '/index.node')) { - return File::clean($name . '/index.node'); + foreach ($this->extensions as $ext) { + if (is_file($path . '/index' . $ext)) { + return $this->as_index[$name] = File::clean($name . '/index' . $ext); + } } + $this->as_index[$name] = false; // ERROR throw new FileNotFoundException(sprintf('File %s could not be be found!', $name)); } @@ -145,8 +164,14 @@ private function asIndex(string $name): string */ private function asDir(string $name): string { - $package_info_path = File::makeAbsolutePath($name . '/package.json', $this->config->getProjectRoot()); + if (isset($this->as_dir[$name])) { + if ($this->as_dir[$name] === false) { + throw new FileNotFoundException(sprintf('File %s could not be be found!', $name)); + } + return $this->as_dir[$name]; + } + $package_info_path = File::makeAbsolutePath($name . '/package.json', $this->config->getProjectRoot()); // 1. If X/package.json is a file, if (is_file($package_info_path)) { // a. Parse X/package.json, and look for "main" field. @@ -155,15 +180,15 @@ private function asDir(string $name): string // b. let M = X + (json main field) // c. LOAD_AS_FILE(M) try { - return $this->asFile($name . '/' . $package_info['main']); + return $this->as_dir[$name] = $this->asFile($name . '/' . $package_info['main']); } catch (FileNotFoundException $e) { // d. LOAD_INDEX(M) - return $this->asIndex($name . '/' . $package_info['main']); + return $this->as_dir[$name] = $this->asIndex($name . '/' . $package_info['main']); } } // 2. LOAD_INDEX(X) - return $this->asIndex($name); + return $this->as_dir[$name] = $this->asIndex($name); } /** @@ -175,6 +200,12 @@ private function asDir(string $name): string */ private function asModule(string $name): string { + if (isset($this->as_module[$name])) { + if ($this->as_module[$name] === false) { + throw new FileNotFoundException(sprintf('File %s could not be be found!', $name)); + } + return $this->as_module[$name]; + } // 1. let DIRS=NODE_MODULES_PATHS(START) $dirs = array_merge(['node_modules'], $this->config->getIncludePaths()); @@ -182,17 +213,18 @@ private function asModule(string $name): string foreach ($dirs as $dir) { // a. LOAD_AS_FILE(DIR/X) try { - return $this->asFile($dir . '/' . $name); + return $this->as_module[$name] = $this->asFile($dir . '/' . $name); } catch (FileNotFoundException $e) { // b. LOAD_AS_DIRECTORY(DIR/X) try { - return $this->asDir($dir . '/' . $name); + return $this->as_module[$name] = $this->asDir($dir . '/' . $name); } catch (FileNotFoundException $e) { continue; // skip } } } + $this->as_module[$name] = false; throw new FileNotFoundException(sprintf('File %s could not be be found!', $name)); } } diff --git a/src/Plugin/AngularPlugin.php b/src/Plugin/AngularPlugin.php index 72b6d30..824c33c 100644 --- a/src/Plugin/AngularPlugin.php +++ b/src/Plugin/AngularPlugin.php @@ -17,7 +17,7 @@ final class AngularPlugin implements PluginInterface { public function activate(PluginApi $plugin_api): void { - $angular_collector = new AngularImportCollector(); + $angular_collector = new AngularImportCollector($plugin_api); if ($plugin_api->getConfig()->isDev()) { $angular_collector = new CachedImportCollector($angular_collector, $plugin_api->getCache()); } diff --git a/src/Plugin/LessPlugin.php b/src/Plugin/LessPlugin.php index 2cdfc7e..72bba3b 100644 --- a/src/Plugin/LessPlugin.php +++ b/src/Plugin/LessPlugin.php @@ -8,6 +8,8 @@ use Hostnet\Component\Resolver\Bundler\Processor\LessContentProcessor; use Hostnet\Component\Resolver\Bundler\Runner\LessRunner; use Hostnet\Component\Resolver\Cache\CachedImportCollector; +use Hostnet\Component\Resolver\Event\AssetEvents; +use Hostnet\Component\Resolver\Event\FindSourceEvent; use Hostnet\Component\Resolver\Import\BuiltIn\LessImportCollector; /** @@ -25,6 +27,15 @@ public function activate(PluginApi $plugin_api): void if ($plugin_api->getConfig()->isDev()) { $less_collector = new CachedImportCollector($less_collector, $plugin_api->getCache()); } + $plugin_api->getConfig()->getEventDispatcher()->addListener( + AssetEvents::FIND_SOURCE, + function (FindSourceEvent $ev) { + $file_path = preg_replace('/\.css$/', '.less', $ev->getFilepath()); + if (file_exists($file_path)) { + $ev->setFilepath($file_path); + } + } + ); $plugin_api->addCollector($less_collector); } } diff --git a/src/Plugin/TsPlugin.php b/src/Plugin/TsPlugin.php index 146839a..be33747 100644 --- a/src/Plugin/TsPlugin.php +++ b/src/Plugin/TsPlugin.php @@ -24,7 +24,7 @@ public function activate(PluginApi $plugin_api): void new JsImportCollector( new FileResolver($plugin_api->getConfig(), ['.ts', '.js', '.json', '.node']) ), - new FileResolver($plugin_api->getConfig(), ['.ts', '.d.ts', '.js', '.json', '.node']) + new FileResolver($plugin_api->getConfig(), ['.ts', '.js', '.json', '.node']) ); if ($plugin_api->getConfig()->isDev()) { $ts_collector = new CachedImportCollector($ts_collector, $plugin_api->getCache()); diff --git a/src/Resources/require.js b/src/Resources/require.js index 7878869..9d9167e 100644 --- a/src/Resources/require.js +++ b/src/Resources/require.js @@ -12,8 +12,8 @@ this.message = 'Cannot initialize module "' + name + '".'; this.parent = parent; }; - var ModuleRedeclareError = function (name) { - this.message = 'Cannot redeclare module "' + name + '".'; + var ModuleRedeclareError = function (name, stacktrace) { + this.message = 'Cannot redeclare module "' + name + '". Previous declaration:\n' + stacktrace; }; RequireError.prototype = new Error(); @@ -77,7 +77,7 @@ // define(["dep1", "dep2"], function (dep_1, dep_2) {}) dependencies = a; - initializer = b; + initializer = typeof b === 'function' ? b : function () { return b; }; } } else { // define("foo", ["dep1", "dep2"], function (dep_1, dep_2) {}) @@ -133,12 +133,13 @@ window.register = function (name, initializer) { if (_modules[name]) { - throw new ModuleRedeclareError(name); + throw new ModuleRedeclareError(name, _modules[name]._stack); } _modules[name] = { _initializer: initializer, - _module: null + _module: null, + _stack: (new TypeError).stack }; }; })(typeof window !== "undefined" ? window : this); diff --git a/test/Bundler/Pipeline/ContentPipelineTest.php b/test/Bundler/Pipeline/ContentPipelineTest.php index cba5da8..d9a1d3c 100644 --- a/test/Bundler/Pipeline/ContentPipelineTest.php +++ b/test/Bundler/Pipeline/ContentPipelineTest.php @@ -64,18 +64,19 @@ public function testPush() $this->config->getSourceRoot()->willReturn('fixtures'); $this->config->getCacheDir()->willReturn(__DIR__ . '/cache/new'); - $input_file = new RootFile(new Module('fixtures/bar.foo', 'fixtures/bar.foo')); + $input_file = new RootFile(new Module('fixtures/bar.foo', 'fixtures/bar.foo', 'test/fixtures/test')); $target_file = new File('output.foo'); $reader = new FileReader(__DIR__); $input_file->addChild($d1 = new Dependency(new File('foo.foo'), true)); $input_file->addChild($d2 = new Dependency(new Module('fixtures/foo/bar.foo', 'fixtures/foo/bar.foo'))); + $input_file->addChild($d3 = new Dependency(new Module('test/fixtures/test', 'fixtures/foo/bla.foo'))); $this->content_pipeline->addProcessor(new IdentityProcessor('foo')); self::assertEquals( - "foobar\nfoobar\n", - $this->content_pipeline->push([$input_file, $d1, $d2], $reader, $target_file) + "foobar\nfoobar\nblaS", + $this->content_pipeline->push([$input_file, $d1, $d2, $d3], $reader, $target_file) ); } diff --git a/test/Bundler/Pipeline/cache/new/035cc_fixtures.foo.bar.foo b/test/Bundler/Pipeline/cache/new/035cc_fixtures.foo.bar.foo deleted file mode 100644 index b8c4f7c..0000000 --- a/test/Bundler/Pipeline/cache/new/035cc_fixtures.foo.bar.foo +++ /dev/null @@ -1,2 +0,0 @@ -a:2:{i:0;s:7:"foobar -";i:1;s:3:"foo";} \ No newline at end of file diff --git a/test/Bundler/Pipeline/cache/new/98d3b_fixtures.bar.foo b/test/Bundler/Pipeline/cache/new/98d3b_fixtures.bar.foo deleted file mode 100644 index b8c4f7c..0000000 --- a/test/Bundler/Pipeline/cache/new/98d3b_fixtures.bar.foo +++ /dev/null @@ -1,2 +0,0 @@ -a:2:{i:0;s:7:"foobar -";i:1;s:3:"foo";} \ No newline at end of file diff --git a/test/Bundler/Pipeline/fixtures/foo/bla.foo b/test/Bundler/Pipeline/fixtures/foo/bla.foo new file mode 100644 index 0000000..5e232bd --- /dev/null +++ b/test/Bundler/Pipeline/fixtures/foo/bla.foo @@ -0,0 +1 @@ +blaS \ No newline at end of file diff --git a/test/Bundler/Processor/TsContentProcessorTest.php b/test/Bundler/Processor/TsContentProcessorTest.php index 8184600..6fcda52 100644 --- a/test/Bundler/Processor/TsContentProcessorTest.php +++ b/test/Bundler/Processor/TsContentProcessorTest.php @@ -55,14 +55,14 @@ public function testPeek() public function testTranspile() { - $item = new ContentItem(new File(basename(__FILE__)), 'foobar.ts', new FileReader(__DIR__)); + $item = new ContentItem(new File(basename(__FILE__)), 'foobar.component.ts', new FileReader(__DIR__)); $this->ts_runner->execute($item)->willReturn('ts code'); $this->ts_content_processor->transpile(__DIR__, $item); self::assertContains('ts code', $item->getContent()); - self::assertSame('foobar', $item->module_name); + self::assertSame('foobar.component', $item->module_name); self::assertSame(ContentState::PROCESSED, $item->getState()->current()); } } diff --git a/test/Bundler/Processor/expected.module.js b/test/Bundler/Processor/expected.module.js index 2cc9448..eec399f 100644 --- a/test/Bundler/Processor/expected.module.js +++ b/test/Bundler/Processor/expected.module.js @@ -1,3 +1,3 @@ -register('foobar.js', function (define, require, module, exports) { +register("foobar.js", function (define, require, module, exports) { console.log("foobar"); }); diff --git a/test/Config/FileConfigTest.php b/test/Config/FileConfigTest.php index 0f402b7..3f22f3e 100644 --- a/test/Config/FileConfigTest.php +++ b/test/Config/FileConfigTest.php @@ -56,7 +56,6 @@ public function testIncludePaths() self::assertSame([], $config->getEntryPoints()); self::assertSame([], $config->getAssetFiles()); self::assertSame(self::EXPECTED_OUTPUT, $config->getOutputFolder()); - self::assertSame('dev', $config->getOutputFolder(false)); self::assertSame('', $config->getSourceRoot()); self::assertSame(__DIR__ . '/../fixtures/configs/var', $config->getCacheDir()); self::assertSame('/usr/bin/node', $config->getNodeJsExecutable()->getBinary()); @@ -68,7 +67,14 @@ public function testIncludePaths() public function testMinimalRelativeNodePaths() { - $config = new FileConfig(__DIR__.'/../fixtures/configs/minimal-relative.config.json', [], true); + $config = new FileConfig( + __DIR__.'/../fixtures/configs/minimal-relative.config.json', + [], + true, + null, + null, + ["web-root" => "web"] + ); self::assertTrue($config->isDev()); self::assertSame(__DIR__.'/../fixtures/configs', $config->getProjectRoot()); diff --git a/test/Event/FindSourceEventTest.php b/test/Event/FindSourceEventTest.php new file mode 100644 index 0000000..96140d2 --- /dev/null +++ b/test/Event/FindSourceEventTest.php @@ -0,0 +1,22 @@ +getFilepath()); + $item->setFilepath(__DIR__ . '/../'); + self::assertEquals(__DIR__ . '/../', $item->getFilepath()); + } +} diff --git a/test/EventListener/AngularHtmlListenerTest.php b/test/EventListener/AngularHtmlListenerTest.php index cb4f7b6..46c018f 100644 --- a/test/EventListener/AngularHtmlListenerTest.php +++ b/test/EventListener/AngularHtmlListenerTest.php @@ -19,6 +19,7 @@ use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Psr\SimpleCache\CacheInterface; +use Symfony\Component\EventDispatcher\EventDispatcher; /** * @covers \Hostnet\Component\Resolver\EventListener\AngularHtmlListener @@ -61,9 +62,12 @@ public function testOnPostTranspile() $item = new ContentItem(new File('app.component.ts'), 'app.component', new StringReader('')); $item->transition(ContentState::READY, file_get_contents(__DIR__ . '/fixtures/app.component.js'), 'js'); + $event_dispatcher = new EventDispatcher(); + $this->config->getProjectRoot()->willReturn(__DIR__ . '/fixtures'); $this->config->getSourceRoot()->willReturn(''); $this->config->getOutputFolder()->willReturn('dev'); + $this->config->getEventDispatcher()->willReturn($event_dispatcher); $less = new File('app.component.less'); $less_root = new RootFile($less); @@ -93,9 +97,12 @@ public function testOnPostTranspileWithSource() $item = new ContentItem(new File('fixtures/test/app.component.ts'), 'app.component', new StringReader('')); $item->transition(ContentState::READY, file_get_contents(__DIR__ . '/fixtures/test/app2.component.js'), 'js'); + $event_dispatcher = new EventDispatcher(); + $this->config->getProjectRoot()->willReturn(__DIR__); $this->config->getSourceRoot()->willReturn('fixtures'); $this->config->getOutputFolder()->willReturn('dev'); + $this->config->getEventDispatcher()->willReturn($event_dispatcher); $less = new File('fixtures/test/app.component.less'); $less_root = new RootFile($less); diff --git a/test/Import/BuiltIn/AngularImportCollectorTest.php b/test/Import/BuiltIn/AngularImportCollectorTest.php index 0158f28..c2f9d74 100644 --- a/test/Import/BuiltIn/AngularImportCollectorTest.php +++ b/test/Import/BuiltIn/AngularImportCollectorTest.php @@ -5,16 +5,21 @@ declare(strict_types=1); namespace Hostnet\Component\Resolver\Import\BuiltIn; +use Hostnet\Component\Resolver\Config\ConfigInterface; use Hostnet\Component\Resolver\File; use Hostnet\Component\Resolver\Import\Import; use Hostnet\Component\Resolver\Import\ImportCollection; +use Hostnet\Component\Resolver\Plugin\PluginApi; use PHPUnit\Framework\TestCase; +use Symfony\Component\EventDispatcher\EventDispatcher; /** * @covers \Hostnet\Component\Resolver\Import\BuiltIn\AngularImportCollector */ class AngularImportCollectorTest extends TestCase { + private $plugin_api; + /** * @var AngularImportCollector */ @@ -22,7 +27,8 @@ class AngularImportCollectorTest extends TestCase protected function setUp() { - $this->angular_import_collector = new AngularImportCollector(); + $this->plugin_api = $this->prophesize(PluginApi::class); + $this->angular_import_collector = new AngularImportCollector($this->plugin_api->reveal()); } /** @@ -47,6 +53,13 @@ public function supportsProvider() public function testCollect() { + $event_dispatcher = new EventDispatcher(); + + $config = $this->prophesize(ConfigInterface::class); + $config->getEventDispatcher()->willReturn($event_dispatcher); + + $this->plugin_api->getConfig()->willReturn($config->reveal()); + $imports = new ImportCollection(); $file = new File('resolver/ts/angular/app.component.ts'); diff --git a/test/Import/BuiltIn/TsImportCollectorTest.php b/test/Import/BuiltIn/TsImportCollectorTest.php index 0305361..b2919a4 100644 --- a/test/Import/BuiltIn/TsImportCollectorTest.php +++ b/test/Import/BuiltIn/TsImportCollectorTest.php @@ -33,7 +33,7 @@ protected function setUp() $this->ts_import_collector = new TsImportCollector( new JsImportCollector(new FileResolver($config->reveal(), ['.ts', '.js', '.json', '.node'])), - new FileResolver($config->reveal(), ['.ts', '.d.ts', '.js', '.json', '.node']) + new FileResolver($config->reveal(), ['.ts', '.js', '.json', '.node']) ); } diff --git a/test/Plugin/LessPluginTest.php b/test/Plugin/LessPluginTest.php index 84237dd..e9f02ca 100644 --- a/test/Plugin/LessPluginTest.php +++ b/test/Plugin/LessPluginTest.php @@ -41,6 +41,7 @@ public function testActivate(string $expected_collector_class, bool $is_dev) $angular_plugin = new LessPlugin(); $angular_plugin->activate($plugin_api); self::assertCount(0, $event_dispatcher->getListeners(AssetEvents::POST_PROCESS)); + self::assertCount(1, $event_dispatcher->getListeners(AssetEvents::FIND_SOURCE)); } public function activateProvider(): array diff --git a/test/fixtures/configs/minimal-relative.config.json b/test/fixtures/configs/minimal-relative.config.json index dc54175..c603528 100644 --- a/test/fixtures/configs/minimal-relative.config.json +++ b/test/fixtures/configs/minimal-relative.config.json @@ -1,6 +1,5 @@ { "files": [], - "web-root": "web", "node": { "bin" : "bin/node", "node_modules" : "node_modules" diff --git a/test/fixtures/resolver/js/commented-require.js b/test/fixtures/resolver/js/commented-require.js new file mode 100644 index 0000000..ac24227 --- /dev/null +++ b/test/fixtures/resolver/js/commented-require.js @@ -0,0 +1 @@ +// this file should not be imported \ No newline at end of file diff --git a/test/fixtures/resolver/js/require-syntax/main.js b/test/fixtures/resolver/js/require-syntax/main.js index ca1c08e..17dc6a3 100644 --- a/test/fixtures/resolver/js/require-syntax/main.js +++ b/test/fixtures/resolver/js/require-syntax/main.js @@ -6,4 +6,7 @@ require('module_package_dir'); require('./relative'); require('../relative'); +/** + * require('../commented-require'); + */ // HENK