# 2.6 主题、测试、格式化

> 原文地址： <https://juejin.cn/post/6972180649625157645>

本文介主题构建、自动化测试、代码质量检查、类型声明。

## 项目主题

### 📁 packages/theme-chalk

项目主题 `theme-chalk` 是一个独立的项目,通过 `gulp` 打包构建生成，支持单独发布。 [ElementUI/theme-chalk 仓库地址](https://github.com/ElementUI/theme-chalk)

`packages/theme-chalk` 下放有字体文件，scss 相关变量、mixin 及公共样式设置，各 UI 组件对应的 scss 文件。项目目录结构如下 👇：

```bash
├─gulpfile.js               # 帮助gulp实现自动化管理项目功能
├─package.json
├─src
|  ├─reset.scss             # 重置浏览器的默认属性
|  ├─index.scss             # 样式入口文件
|  ├─base.scss              # 基础 引入动画 、图标样式
|  ├─icon.scss              # 图标样式
...
|  ├─button.scss            # 组件对应单独的scss文件
|  ├─upload.scss            # 组件对应单独的scss文件
...
|  ├─mixins                 # 混入(mixin)定义
|  |   ├─config.scss        # 变量
|  |   ├─function.scss      # 自定义函数 @fuction
|  |   ├─mixins.scss        # 支持接收参数
|  |   ├─utils.scss         # 公共样式
|  |   └button.scss         # 按钮公共样式
|  ├─fonts  # 字体图标
|  ├─date-picker            # 日期时间选择器样式
|  ├─common
|  |   ├─transition.scss    # 动画
|  |   └var.scss            # 主题sass变量
├─lib                       # 打包输出目录
```

### @mixin 与 @include

`@mixin` 指令允许我们定义一个可以在整个样式表中重复使用的样式。

`@include` 指令可以将混入（mixin）引入到文档中。

混入(mixin)通过 @mixin 指令来定义。创建一个名为 "important-text" 的混入：

```css
@mixin important-text {
  color: red;
  font-size: 25px;
  font-weight: bold;
  border: 1px solid blue;
}
```

@include 指令可用于包含一混入,包含 important-text 混入代码如下：

![carbon (48).png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f86f4543e7cd46889803c8ed20fcb045~tplv-k3u1fbpfcp-watermark.image)

```css
/* @include实例 */
.danger {
  @include important-text;
  background-color: green;
}
将以上代码转换为 CSS 代码，如下所示：

/* 转换为 CSS 代码 */
.danger {
  color: red;
  font-size: 25px;
  font-weight: bold;
  border: 1px solid blue;
  background-color: green;
}
```

### 主题构建

![image.png](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/557bf008c05644cb90fb32463ffe14e8~tplv-k3u1fbpfcp-watermark.image)

#### 1️⃣ 生成入口文件

`build/bin/gen-cssfile` 找到 `components.json`， 获取组件列表，找到`packages/theme-chalk/src`目录下对应的各组件的 `component-name.scss` 文件，以`@import "./component-name.scss"`的形式，写入`packages/theme-chalk/index.scss`文件-样式总入口文件。若是组件对应的样式不存在，会自动创建遗漏的样式文件。

#### 2️⃣ 构建主题

`gulp`是一种基于流(stream)的自动化构建工具，`gulpfile.js` 定义两个任务(task):

* 将`packages/theme-chalk/src`目录下的 scss 文件转换成 css 文件，输出至`packages/theme-chalk/src/lib`目录下;
* 将`packages/theme-chalk/src/fonts`目录下的字体图标文件压缩处理，输出至 `packages/theme-chalk/src/lib/fonts` 目录下。

![carbon (50).png](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d27799bc66554e6b89a1783278a9e206~tplv-k3u1fbpfcp-watermark.image)

#### 3️⃣ 拷贝至 lib/theme-chalk 下

通过`cp-cli`，将`packages/theme-chalk/src/lib`目录下文件拷贝至`lib/theme-chalk`目录下。

## 项目测试

### test\ssr\require.test.js

SSR 引入类库(require)测试, `build\release.sh`文件执行 `node test/ssr/require.test.js` 命令。

```js
const path = require("path");

try {
  process.env.VUE_ENV = "server";
  require(path.join(process.env.PWD, "./lib/index"));
  console.log("SSR require test PASS");
} catch (e) {
  console.error("SSR require test error");
  throw Error(e);
}
```

### 📁 test/unit 单元测试

项目通过执行 `npm run test` `npm run test:watch` 运行单元测试，使用如下技术：

* `karma` 测试执行过程管理工具(Test Runner)。
* `Mocha` 是运行在 Node.js 和浏览器上的功能丰富的 JavaScript 测试框架。
* `Chai` 是一个用于 Node.js 和浏览器的 BDD/TDD 断言库，可以与任何 JavaScript 测试框架便捷配对。
* `Sinon.JS` 用于对 JavaScript 隔离测试 spy, stub 和 mock。适用于任何单元测试框架。

目录结构如下 👇：

```js
├─index.js			    # 入口文件
├─karma.conf.js			    # karma配置
├─util.js                           # 公共方法
├─specs                             # 测试用例
|   ├─alert.spec.js                 # 测试用例脚本 [组件名].spec.js
|   ├─button.spec.js
...
...
|   ├─upload.spec.js
|   ├─util.clickoutside.spec.js
|   └util.vue-popper.spec.js
├─mocks                             # 模拟数据
|   └uri.js
├─coverage                          # 测试覆盖率报告
|    ├─lcov.info                    # 报告信息
|    ├─lcov-report                  # 报告网站
```

`karma.conf.js` 测试配置信息。

![carbon (95).png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9f0c3e1cca384d389d5771dc8c6793da~tplv-k3u1fbpfcp-watermark.image)

`index.js` 测试入口文件，单元测试默认测试 `src` 目录下除了 main.js 之外的所有文件，根据实际情况调整测试范围。

![image.png](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b479e39eb6694a91a35cdf1fe8d5a109~tplv-k3u1fbpfcp-watermark.image)

测试脚本命名方式为 `[组件名].spec.js` , 统一放在 `test/unit/specs/` 目录下，语法结构如下 👇。

![image.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/26de93c182cc44cb93ff621db11d3b43~tplv-k3u1fbpfcp-watermark.image)

如果测试成功，终端输出测试覆盖率概览 👇。

![image.png](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/1f574b69ac0c48a8975c1f5cfd51b4c5~tplv-k3u1fbpfcp-watermark.image)

同时`karma-coverage` 会在 `test/unit/coverage` 文件夹中生成测试覆盖率结果的概览信息`lcov.info`和网页 `lcov-report/**`。

生成测试覆盖率结果的网站,在浏览其中打开，内容如下 👇：

![image.png](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/8a0e16640c2740baa6113f414245cc53~tplv-k3u1fbpfcp-watermark.image)

## 代码质量检查

element 使用了 `eslint` 进行代码风格检测，辅助编码规范执行，有效控制代码质量，实现项目代码风格统一。 编写发布了 eslint 的扩展规则配置-- [eslint-config-elemefe](https://www.npmjs.com/package/eslint-config-elemefe) 。

`eslint` 所能提供的格式化功能很有限；而 `prettier` 在格式化代码方面具有更大优势。可以集成 `prettier` 负责格式限制、自动格式化，详细配置参考[代码风格检查和格式化配置（ESlint ＆ Prettier）](https://juejin.cn/post/6951808773354684447)。

## 类型声明

`types` 目录存放组件的 `TypeScript` 声明文件，以 `.d.ts` 后缀结尾。提升`typescript` 项目中引入组件库的开发体验，需要在 `package.json` 中指定 `typing` 属性的值， 声明的入口文件才能生效。

```json
{
  "typings": "types/index.d.ts"
}
```

## 关联阅读

点击以下链接，可以快速查看本系列其他文章：\
[专栏/Element 2.X 源码学习](https://juejin.cn/column/6961321064110489631)

👇 项目工程化系列文章链接如下，推荐按照顺序阅读文章 👇。

1️⃣ [源码剖析之工程化：项目概览、package.json、npm script](https://juejin.cn/post/6969258163136626725)\
2️⃣ [源码剖析之工程化：项目构建、MD 解析](https://juejin.cn/post/6969933702759940133)\
3️⃣ [源码剖析之工程化：打包配置](https://juejin.cn/post/6970691644114862111/)\
4️⃣ [源码剖析之工程化：发布部署、持续集成](https://juejin.cn/post/6971054455139598366/)\
5️⃣ [源码剖析之工程化：主题构建、自动化测试、代码质量检查、类型声明](https://juejin.cn/post/6971434343516340238)\
6️⃣ [源码剖析之工程化：项目网站](https://juejin.cn/post/6972180649625157645)\
7️⃣ [源码剖析之工程化：命令之图解](https://juejin.cn/post/6991347082552573965)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://anduril.gitbook.io/learning-element/chapter02_fee/2.6-zhu-ti-ce-shi-ge-shi-hua.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
