尝试将aframe集成到angular2项目中时出现各种错误。单元测试

时间:2017-09-28 08:10:53

标签: angular aframe

我在我的角度4.3.6(angular-cli 1.0.0)项目中正确地使用aframe 0.7.0时遇到了问题。我得到的一些信息:

Chrome 61.0.3163 (Windows 10 0.0.0) LOG: '%cA-Frame:warn %cPut the A-Frame <script> tag in the <head> of the HTML *before* the scene to ensure everything for A-Frame is properly registered before they are used from HTML.%c ', 'color: orange', 'color: inherit', 'color: orange'

和: 'a-assets' is not a known element: 1. If 'a-assets' is an Angular component, then verify that it is part of this module. 2. If 'a-assets' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message. (" lss-aframe-component tats #introScene> <!-- <ng-template appGameScene></ng-template> --> [ERROR ->]<a-assets>

与其他JS库不同,aframe的一个重大问题是要求它从<head>元素而不是<body>元素加载。

我在stackoverflow here herehere上找到了一些部分解决方案,但是所提供的解决方案都没有在我的所有服务中使用&#39;并且&#39; ng test&#39;环境。特别是,我很难在单元测试中处理引用AFRAME命名空间的组件。

您需要做什么才能将aframe集成到Angular2环境中,包括单元测试?

2 个答案:

答案 0 :(得分:3)

这是我必须要做的才能让一个框架完全集成到角度。我并不是说这是最好的方式,或必须做这一切。有些人似乎能够使用更简单的解决方案,如果这些解决方案适用于您(例如只需adding the aframe lib into polyfill.ts),那就去做吧。显然,解决方案可能因角度释放而异,如果您没有运行单元测试,那么您不需要做我在此描述的所有内容。

您需要关注的重要文件是:

.angular-cli.json
karma.conf.js
src/app/app.module.ts
src/index.html
all your .spec.ts files

ng服务环境

1)为了获得您的服务&#39; (web)环境从头部加载aframe.js,将aframe.js lib添加到&#39; src / index.html&#39;像这样:

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>My app</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
  <script src="../node_modules/aframe/dist/aframe-master.js"></script>
  ...

注意:您不需要为three.js添加脚本标记,因为aframe会预先请求它。

注2:您还可以使用&#39; node_modules&#39; /aframe/build/aframe.js'。 &#39; AFRAME-master.js&#39;是一个更加不稳定的出血边缘&#39;构建,但它对我来说足够好。

Note 3(已更新&#39; 2018-01-10&#39;):虽然我似乎能够使用&#34; ../ node_modules&#34;角度4,角度5我必须复制&aframe-master.js&#39;和&#39; aframe-master.js.map&#39;进入资产的子目录&#39;例如&#39; SRC /资产/库&#39 ;.简而言之,angular 5似乎要求从&#39; / assets&#39;中加载外部js库。 (?)。

通常情况下,您应该在scripts的{​​{1}}标记中加入javascript库,但如果您将它们放在那里,则无法从头部加载。我的.angular.cli.json标记目前为空,但您在其中放置任何其他js库并且在index.html中:

scripts

请注意脚本是空白的,并且包含aframe.js

2)添加&#39; CUSTOM_ELEMENTS_SCHEMA&#39;到&#39; src / app / app.module.ts&#39;:

cat .angular-cli.json
{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "project": {
    "name": "lss"
  },
  "apps": [
    {
      "root": "src",
      "outDir": "dist",
      "assets": [
        "assets",
        "favicon.ico"
      ],
      "index": "index.html",
      "main": "main.ts",
      "polyfills": "polyfills.ts",
      "test": "test.ts",
      "tsconfig": "tsconfig.app.json",
      "testTsconfig": "tsconfig.spec.json",
      "prefix": "app",
      "styles": [
        "styles.css"
      ],
      "scripts": [
      ],
      "environmentSource": "environments/environment.ts",

注意:CUSTOM_ELEMENTS_SCHEMA允许在角度html中使用非角度标记(例如import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; ... entryComponents: [AppComponent, PlaneSceneComponent], bootstrap: [AppComponent], schemas: [ CUSTOM_ELEMENTS_SCHEMA ] }) export class AppModule { } )。

如果您没有运行单元测试,那就差不多了。业力测试环境完全与标准的基于Web的环境分离。如果您正在计划进行单元测试,请执行以下附加步骤来设置测试环境。

ng测试环境

3)更新karma.conf.js以了解aframe和three.js并指定自定义上下文文件:

- &GT;更新2018-03-08:从angular cli 1.7.3开始,&#39; customContextFile&#39;似乎不再受角度的尊重。它似乎也无法再从node_modules读取文件 - 您必须将 aframe-master.lib 放在&s; /rc / assets /&#39;下。我不得不直接编辑节点_modules/@angular/cli/plugins/karma-context.html'像这样:

<a-scene>

不幸的是,在我找到更正式的方法来实现这种效果之前,必须在每个签出的仓库上手动执行此hack,因为大多数人都不会检查node_modules目录。 以下工作在ng ng-cli 1.7.3:

<head>
  <title></title>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
  <!--user add -->
  <script type="text/javascript" src="/base/src/assets/libs/aframe-master.js" crossorigin="anonymous"></script>
  <!--user end -->
</head>

注意:&#39; //用户添加&#39;包围的代码部分和&#39; //用户端&#39;块。第一个定义了一个新的&#39; context.html&#39;我们将创建的文件将从module.exports = function (config) { config.set({ basePath: '', frameworks: ['jasmine', '@angular/cli'], plugins: [ require('karma-jasmine'), require('karma-chrome-launcher'), require('karma-jasmine-html-reporter'), require('karma-coverage-istanbul-reporter'), require('@angular/cli/plugins/karma') ], //user add customContextFile: './src/environments/context_aframe_ut.html', //user end client:{ clearContext: false // leave Jasmine Spec Runner output visible in browser }, files: [ { pattern: './src/test.ts', watched: false }, //user add { pattern: 'node_modules/aframe/dist/aframe-master.js', included: false, served: true }, { pattern: 'node_modules/three/build/three.js', included: false, served: true } //user end ], preprocessors: { './src/test.ts': ['@angular/cli'] }, mime: { 'text/x-typescript': ['ts','tsx'] }, coverageIstanbulReporter: { reports: [ 'html', 'lcovonly' ], fixWebpackSourcePaths: true }, angularCli: { environment: 'dev' }, reporters: config.angularCli && config.angularCli.codeCoverage ? ['progress', 'coverage-istanbul'] : ['progress', 'kjhtml'], port: 9876, colors: true, logLevel: config.LOG_INFO, autoWatch: true, browsers: ['Chrome'], singleRun: false }); }; 标记加载aframe.js。第二个将aframe和three.js库定义为业力。

4)创建一个新的业力上下文html文件以从头部加载aframe。

- &GT;更新2018-03-08:请注意ang-cli 1.7.3,因为&#39; customContextFile&#39;不再受到尊重,你不必做这一步。编辑&#39; node_modules/@angular/cli/plugins/karma-context.html'如前一步骤所述。

复制文件&#39; node_modules / karma / static / context.html&#39;到你的&#39; customContextFile&#39;以前定义的目录,并像这样修改:

<head>

注意:&#39; //用户添加&#39;和&#39; //用户端&#39;部分再次。
注意2:你必须在aframe lib前加上&#39; / base&#39;为了业力找到它。请注意我的中止尝试使非前缀版本工作。
注3 :(可选)在开场评论中加入一些文字,例如&#39; vt在这里&#39;这样您就可以更轻松地验证Karma确实正在加载您的自定义context.html。

5)(可选)验证更新的context.html。

运行测试&#39;并检查浏览器使用的html。在节点&iframe下验证。#document.html.head&#39;你有:

<!DOCTYPE html> <!-- This is the execution context. Loaded within the iframe. Reloaded before every execution run. vt was here 3. --> <html> <head> <title></title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" /> <!--user add --> <!-- <script src="aframe-master.js"></script> --> <script src="/base/node_modules/aframe/dist/aframe-master.js"></script> <!--user end --> </head> <body> <!-- The scripts need to be in the body DOM element, as some test running frameworks need the body to have already been created so they can insert their magic into it. For example, if loaded before body, Angular Scenario test framework fails to find the body and crashes and burns in an epic manner. --> <script src="context.js"></script> <script type="text/javascript"> // Configure our Karma and set up bindings %CLIENT_CONFIG% window.__karma__.setupContext(window); // All served files with the latest timestamps %MAPPINGS% </script> <!-- Dynamically replaced with <script> tags --> %SCRIPTS% <script type="text/javascript"> window.__karma__.loaded(); </script> </body> </html>

这证实了业力从头部加载了aframe。

6)添加&#39; CUSTOM_ELEMENTS_SCHEMA&#39;对于每个使用a-frame的spec.ts文件:

<script src="/base/node_modules/aframe/dist/aframe-master.js"></script>

7)你可能需要循环服务&#39;并且&#39; ng test&#39;为了了解变化。

结论

正如您所看到的,这并非完全无足轻重。问题的主要来源是要求从头部加载帧。我希望这可以节省一些人为了将aframe完全集成到angular2环境中而付出的所有努力。

我还应该声明我非常喜欢A-frame,它的角度非常好。将这两个框架组合在一起是一个很好的组合,它绝对值得付出努力,所以如果您遇到配置问题,请不要气馁。

答案 1 :(得分:0)

更新了@ vt5491的解决方案,以解决Angular单元测试中的问题

这取决于您在应用程序中使用A-Frame的方式,这对您而言可能是问题,也可能不是问题。但是,一旦您的测试期望在DOM或AFRAME中定义THREEwindow,然后在<head>的{​​{1}}中导入A-Frame可以破坏并停止单元测试的运行。

可以通过创建一个调用index.html的基本脚本文件来重现此错误。您可能需要创建自己的A-Frame组件并将其导入Angular组件:

AFRAME

// foo.script.js AFRAME.registerComponent('foo', { schema: {}, init: function () {}, update: function () {}, tick: function () {}, remove: function () {}, pause: function () {}, play: function () {} }); 导入到要使用的Angular组件中:

foo.script.js

该应用程序将在// foo.component.ts import 'src/script/foo.script.js'; 下正常运行。这是因为ng serve包含A-Frame。

index.html

您将在A-Frame正确启动的地方看到预期的console.log:

  

A-Frame版本:0.9.2(日期2019-05-06,提交#f57a1fa)

     

三个版本(https://github.com/supermedium/three.js):^ 0.102.2

     

WebVR Polyfill版本:^ 0.10.10

但是,当我们运行// index.html <head> <meta charset="utf-8"> <title>Aframe</title> ... <script src="../node_modules/aframe/dist/aframe-master.js"></script> </head> 时,您会注意到控制台中缺少相同的提示。此处不包括A框架。 Karma执行单元测试时不包括A-Frame。相反,业力将中断,并且您的测试将无法完全运行。

  

./ src / scripts / foo.script.js?:3未捕获的ReferenceError:未定义AFRAME

业力的ng t文件位于:

.html node_modules\@angular-devkit\build-angular\src\angular-cli-files\plugins\karma-context.html

一旦此处包含A-Frame的导入(node_modules\@angular-devkit\build-angular\src\angular-cli-files\plugins\karma-debug.html),则您的单元测试将包括A-Frame并正常运行:

karma-context.html

我们可以通过创建自己的// karma-context.html <head> <title></title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" /> <script src="https://aframe.io/releases/1.0.1/aframe.min.js"></script> </head> karma-context.html来自动进行以后的测试。在karma-debug.html目录下,为两个包括A框架导入的scripts文件分别创建一个副本。保持html文件夹中的karma-context.htmlkarma-debug.html不变。克隆您的项目时,内部的更改不会传播,因此我们的修改需要保留在其他地方。

创建一个脚本,将在运行业力时将修改后的node_modules复制到node_module中:

html

将脚本包括在// scripts/karma-copy.test.js const fs = require('fs'); // Modify karma-context.html fs.copyFile( 'src/scripts/karma-context.html', 'node_modules/@angular-devkit/build-angular/src/angular-cli-files/plugins/karma-context.html', (err) => { if (err) throw err; } ); // Modify karma-debug.html fs.copyFile( 'src/scripts/karma-debug.html', 'node_modules/@angular-devkit/build-angular/src/angular-cli-files/plugins/karma-debug.html', (err) => { if (err) throw err; } ); 中:

karma.config.js

现在,当您关闭项目时,plugins: [ require('../src/scripts/karma-copy.test.js'), ... ], 将在ng t中包含A-Frame。