提交 eca8a61b 编写于 作者: U ULIVZ

test: init @vuepress/test-utils and migrate all tests

上级 d708d331
import Content from '@/app/components/Content'
import Content from '../../lib/app/components/Content'
import { mount } from '@vue/test-utils'
import { getRouter, modeTestRunner } from '../util'
import modeTestRunner from '@vuepress/test-utils/modeTestRunner'
import getRouter from '@vuepress/test-utils/getRouter'
function test (mode, localVue) {
it(`${mode} - add custom class by default.`, () => {
......
import {
isIndexFile,
fileToPath
} from '@/prepare/util.js'
import { isIndexFile, fileToPath } from '../../lib/prepare/util.js'
describe('prepare - util', () => {
test('isIndexFile', () => {
......
......@@ -2,7 +2,7 @@ import {
parseHeaders,
removeNonCodeWrappedHTML,
deeplyParseHeaders
} from '@/util/parseHeaders'
} from '../../lib/util/parseHeaders'
describe('parseHeaders', () => {
test('should unescape html', () => {
......
......@@ -6,6 +6,7 @@ import { routes } from '@internal/routes'
import { siteData } from '@internal/siteData'
import appEnhancers from '@internal/app-enhancers'
import globalUIComponents from '@internal/global-ui'
import I18n from '@internal/i18n'
// generated from user config
import('@temp/style.styl')
......@@ -31,7 +32,7 @@ if (module.hot) {
Vue.config.productionTip = false
Vue.use(Router)
// mixin for exposing $site and $page
Vue.mixin(dataMixin(siteData))
Vue.mixin(dataMixin(I18n, siteData))
// component for rendering markdown content and setting title etc.
Vue.component('Content', Content)
Vue.component('OutboundLink', OutboundLink)
......
/* global VUEPRESS_TEMP_PATH */
import Vue from 'vue'
import I18n from '@internal/i18n'
export default function dataMixin (siteData) {
export default function dataMixin (I18n, siteData) {
prepare(siteData)
const store = new Vue({
data: {
......
__tests__
__mocks__
\ No newline at end of file
# @vuepress/test-utils
> test-utils for vuepress
\ No newline at end of file
const defaultJestConfig = require('./jest/jest.config')
module.exports = function createJestConfig (override) {
return Object.assign({}, defaultJestConfig, override)
}
const execa = require('execa')
const rawArgs = process.argv.slice(2)
module.exports = function createJestRunner (jestArgs) {
return async function () {
console.log(`running jest with args: ${jestArgs.join(' ')}`)
await execa('jest', [
...jestArgs,
...rawArgs
], {
stdio: 'inherit'
})
}
}
module.exports = {
dest: 'vuepress',
locales: {
'/': {
lang: 'en-US',
title: 'VuePress',
description: 'Vue-powered Static Site Generator'
},
'/zh/': {
lang: 'zh-CN',
title: 'VuePress',
description: 'Vue 驱动的静态网站生成器'
}
},
themeConfig: {
repo: 'vuejs/vuepress',
editLinks: true,
docsDir: 'docs',
locales: {
'/': {
label: 'English',
selectText: 'Languages',
editLinkText: 'Edit this page on GitHub',
lastUpdated: 'Last Updated'
},
'/zh/': {
label: '简体中文',
selectText: '选择语言',
editLinkText: '在 GitHub 上编辑此页',
lastUpdated: '上次更新',
}
}
}
}
const Router = require('vue-router')
module.exports = function () {
return new Router()
}
// https://github.com/facebook/jest/tree/master/packages/babel-jest
// TODO remove 'babel-core@^7.0.0-0' when babel-jest can work with '@babel/core'
const path = require('path')
module.exports = {
rootDir: path.resolve(__dirname, '..'),
verbose: true,
testURL: 'http://localhost/',
moduleFileExtensions: [
'js',
'vue'
],
testPathIgnorePatterns: [
'test.js',
path.resolve(__dirname, '../test')
],
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/$1'
},
transform: {
'^.+\\.js$': '<rootDir>/node_modules/babel-jest',
'.*\\.(vue)$': '<rootDir>/node_modules/vue-jest'
},
snapshotSerializers: [
'<rootDir>/node_modules/jest-serializer-vue'
]
}
const { fs } = require('@vuepress/shared-utils')
const path = require('path')
const docsBaseDir = path.resolve(__dirname, 'fixtures')
const docsModeNames = fs.readdirSync(docsBaseDir)
const docsModes = docsModeNames.map(name => {
const docsPath = path.resolve(docsBaseDir, name)
const docsTempPath = path.resolve(docsPath, '.vuepress/.temp')
return { name, docsPath, docsTempPath }
})
exports.docsModes = docsModes
......@@ -10,7 +10,7 @@ const Component = {
// When the child component is a pure presentation component,
// we want to be able to display a sub-component with minimal info,
// rather than stubbing it directly.
export function mockComponent (name) {
module.exports = function mockComponent (name) {
return {
render (h) {
return h(Component, { props: { name }})
......
const { createLocalVue } = require('@vue/test-utils')
const dataMixin = require('@vuepress/core/lib/app/dataMixin').default
const I18n = require('@vuepress/core/lib/prepare/I18n')
const Router = require('vue-router')
const mockComponent = require('./mockComponent')
const { docsModes } = require('./meta')
function getLocalVueByMode (mode) {
const localVue = createLocalVue()
localVue.use(Router)
// register global component
localVue.component('OutboundLink', mockComponent('outbound-link'))
const { siteData } = require(`${mode.docsTempPath}/internal/siteData.js`)
localVue.component(siteData.pages[0].key, mockComponent('page-component'))
localVue.mixin(dataMixin(I18n, siteData))
return localVue
}
/**
* Used to test components in VuePress at different mode.
* Since VuePress has two main modes, i18n or normal mode, we need to make
* sure that the core Vue components in VuePress work well in both modes.
* @param description
* @param testFn
*/
module.exports = function modeTestRunner (description, testFn) {
docsModes.forEach(mode => {
describe(description, () => {
testFn(mode.name, getLocalVueByMode(mode))
})
})
}
{
"name": "@vuepress/test-utils",
"version": "1.0.0",
"description": "test-utils for vuepress",
"publishConfig": {
"access": "public"
},
"repository": {
"type": "git",
"url": "git+https://github.com/vuejs/vuepress.git"
},
"keywords": [
"documentation",
"vue",
"vuepress",
"generator"
],
"dependencies": {
"@vuepress/core": "^1.0.0",
"@vuepress/shared-utils": "^1.0.0",
"@vue/test-utils": "^1.0.0-beta.16",
"@babel/core": "^7.0.0-beta.47",
"@babel/preset-env": "^7.0.0-beta.47",
"babel-core": "^7.0.0-0",
"babel-jest": "^23.0.0",
"jest": "^23.0.0",
"jest-serializer-vue": "^1.0.0",
"vue-jest": "^2.6.0",
"execa": "^0.10.0"
},
"author": "Evan You",
"license": "MIT",
"bugs": {
"url": "https://github.com/vuejs/vuepress/issues"
},
"homepage": "https://github.com/vuejs/vuepress/packages/@vuepress/test-utils#readme"
}
\ No newline at end of file
const { fs, logger } = require('@vuepress/shared-utils')
const prepare = require('@vuepress/core/lib/prepare')
const { docsModes } = require('./meta')
async function prepareForTest () {
await Promise.all(docsModes.map(async ({ docsPath, docsTempPath }) => {
await fs.ensureDir(docsTempPath)
await prepare(docsPath, { theme: 'default', temp: docsTempPath })
}))
}
module.exports = function globalSetup () {
logger.wait('Start preparing for testing ...')
return prepareForTest().then(() => {
logger.wait('Finished preparing for testing ...')
})
}
import { mount, RouterLinkStub } from '@vue/test-utils'
import DropdownLink from '@/default-theme/DropdownLink.vue'
import { modeTestRunner } from '../util'
import DropdownLink from '../../src/DropdownLink.vue'
import modeTestRunner from '@vuepress/test-utils/modeTestRunner'
function test (mode, localVue) {
it(`$${mode} - renders dropdown link.`, () => {
......
import { mount, RouterLinkStub } from '@vue/test-utils'
import { modeTestRunner } from '../util'
import NavLink from '@/default-theme/NavLink.vue'
import modeTestRunner from '@vuepress/test-utils/modeTestRunner'
import NavLink from '../../src/NavLink.vue'
function test (mode, localVue) {
it(`$${mode} - renders nav link with internal link`, () => {
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`DropdownLink $i18n - renders dropdown link. 1`] = `
exports[`DropdownLink $docs-i18n - renders dropdown link. 1`] = `
<div class="dropdown-wrapper">
<a class="dropdown-title"><span class="title">VuePress</span> <span class="arrow right"></span></a>
<ul class="nav-dropdown" style="display: none;" name="dropdown">
......@@ -16,7 +16,7 @@ exports[`DropdownLink $i18n - renders dropdown link. 1`] = `
</div>
`;
exports[`DropdownLink $simple - renders dropdown link. 1`] = `
exports[`DropdownLink $docs-simple - renders dropdown link. 1`] = `
<div class="dropdown-wrapper">
<a class="dropdown-title"><span class="title">VuePress</span> <span class="arrow right"></span></a>
<ul class="nav-dropdown" style="display: none;" name="dropdown">
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`NavLink $i18n - renders nav link with external link 1`] = `
exports[`NavLink $docs-i18n - renders nav link with external link 1`] = `
<a href="http://vuejs.org/" target="_blank" rel="noopener noreferrer" class="nav-link external">
Vue
<p class="component outbound-link">outbound-link</p>
</a>
`;
exports[`NavLink $i18n - renders nav link with internal link 1`] = `<a class="nav-link">VuePress</a>`;
exports[`NavLink $docs-i18n - renders nav link with internal link 1`] = `<a class="nav-link">VuePress</a>`;
exports[`NavLink $simple - renders nav link with external link 1`] = `
exports[`NavLink $docs-simple - renders nav link with external link 1`] = `
<a href="http://vuejs.org/" target="_blank" rel="noopener noreferrer" class="nav-link external">
Vue
<p class="component outbound-link">outbound-link</p>
</a>
`;
exports[`NavLink $simple - renders nav link with internal link 1`] = `<a class="nav-link">VuePress</a>`;
exports[`NavLink $docs-simple - renders nav link with internal link 1`] = `<a class="nav-link">VuePress</a>`;
// https://github.com/facebook/jest/tree/master/packages/babel-jest
// TODO remove 'babel-core@^7.0.0-0' when babel-jest can work with '@babel/core'
const path = require('path')
const createJestConfig = require('@vuepress/test-utils/createJestConfig')
module.exports = {
module.exports = createJestConfig({
rootDir: path.resolve(__dirname, '..'),
verbose: true,
testURL: 'http://localhost/',
moduleFileExtensions: [
'js',
'vue'
],
testPathIgnorePatterns: [
'test.js',
path.resolve(__dirname, '../test')
],
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/$1'
},
transform: {
'^.+\\.js$': '<rootDir>/node_modules/babel-jest',
'.*\\.(vue)$': '<rootDir>/node_modules/vue-jest'
'^@/(.*)$': '<rootDir>/$1',
'^@core/(.*)$': '<rootDir>/packages/@vuepress/core/$1'
},
snapshotSerializers: [
'<rootDir>/node_modules/jest-serializer-vue'
]
}
globalSetup: '<rootDir>/packages/@vuepress/test-utils/prepare.js'
})
const execa = require('execa')
const minimist = require('minimist')
const createJestRunner = require('@vuepress/test-utils/createJestRunner')
const rawArgs = process.argv.slice(2)
const args = minimist(rawArgs)
......@@ -12,19 +12,15 @@ if (args.p) {
rawArgs.splice(i, 2)
}
;(async () => {
const jestArgs = [
'--env', 'node',
const jestRunner = createJestRunner(
[
'--config', 'scripts/jest.config.js',
'--runInBand',
...rawArgs,
...(regex ? [regex] : [])
]
console.log(`running jest with args: ${jestArgs.join(' ')}`)
await execa('jest', jestArgs, {
stdio: 'inherit'
})
})().catch(err => {
err
])
;(jestRunner)().catch(err => {
console.error(err)
process.exit(1)
})
const path = require('path')
const fs = require('fs-extra')
const prepare = require('../lib/prepare')
const logger = require('../lib/util/logger')
const tempPath = path.resolve(__dirname, '.temp')
const siteDatePath = path.resolve(__dirname, '../lib/app/.temp/siteData.js')
async function prepareForTest () {
await fs.ensureDir(tempPath)
await prepare(path.resolve(__dirname, '../docs'))
await fs.copy(siteDatePath, path.join(tempPath, 'siteData-i18n.js'))
await prepare(path.resolve(__dirname, 'docs-simple'))
await fs.copy(siteDatePath, path.join(tempPath, 'siteData-simple.js'))
}
prepareForTest().then(() => {
logger.wait('Preparing for testing ...')
})
import path from 'path'
import resolveOptions from '@/prepare/resolveOptions.js'
const DEFAULT_THEME_PATH = path.resolve(__dirname, '../../lib/default-theme')
const DEFAULT_THEME_LAYOUT_PATH = path.resolve(DEFAULT_THEME_PATH, 'Layout.vue')
const DEFAULT_THEME_NOT_FOOUND_PATH = path.resolve(DEFAULT_THEME_PATH, 'NotFound.vue')
describe('prepare - resolveOptions', () => {
test('single file docs without config.', async () => {
const { docsDir } = getDocsPaths('docs-simple')
const options = await resolveOptions(docsDir)
const {
siteConfig,
siteData,
sourceDir,
outDir,
publicPath,
pageFiles,
pagesData,
themePath,
themeLayoutPath,
themeNotFoundPath,
themeEnhanceAppPath,
useDefaultTheme,
isAlgoliaSearch,
markdown
} = options
expect(siteConfig).toEqual({})
expect(siteData).toEqual({
title: '',
description: '',
base: '/',
pages: pagesData,
themeConfig: {},
locales: undefined
})
expect(sourceDir).toBe(docsDir)
expect(outDir).toBe(path.resolve(docsDir, '.vuepress/dist'))
expect(publicPath).toBe('/')
expect(pageFiles).toHaveLength(1)
expect(pageFiles[0]).toBe('README.md')
expect(themePath).toBe(DEFAULT_THEME_PATH)
expect(themeLayoutPath).toBe(DEFAULT_THEME_LAYOUT_PATH)
expect(themeNotFoundPath).toBe(DEFAULT_THEME_NOT_FOOUND_PATH)
expect(themeEnhanceAppPath).toBe(null)
expect(useDefaultTheme).toBe(true)
expect(isAlgoliaSearch).toBe(false)
expect(typeof markdown).toBe('object')
})
test('single file docs with config', async () => {
const { docsDir, configPath } = getDocsPaths('docs-simple-config')
const options = await resolveOptions(docsDir)
const {
siteConfig,
outDir,
publicPath
} = options
expect(siteConfig).toEqual(require(configPath))
expect(siteConfig.base).toBe('vuepress')
expect(siteConfig.dest).toBe('vuepress')
expect(outDir).toBe(path.resolve('vuepress'))
expect(publicPath).toBe('vuepress')
})
test('simple docs with custom theme', async () => {
const paths = getDocsPaths('docs-custom-theme')
const options = await resolveOptions(paths.docsDir)
const {
themePath,
themeLayoutPath,
themeNotFoundPath,
useDefaultTheme
} = options
expect(useDefaultTheme).toBe(false)
expect(themePath).toBe(paths.themePath)
expect(themeLayoutPath).toBe(paths.themeLayoutPath)
expect(themeNotFoundPath).toBe(DEFAULT_THEME_NOT_FOOUND_PATH) // fallbacks to default theme's NotFound component.
})
})
function getDocsPaths (name) {
const docsDir = path.join(__dirname, `fixtures/${name}`)
const configPath = path.join(docsDir, '.vuepress/config.js')
const themePath = path.join(docsDir, '.vuepress/theme')
const themeLayoutPath = path.join(themePath, 'Layout.vue')
const themeNotFoundPath = path.join(themePath, 'NotFound.vue')
return {
docsDir,
configPath,
themePath,
themeLayoutPath,
themeNotFoundPath
}
}
import { createLocalVue } from '@vue/test-utils'
import dataMixin from '@/app/dataMixin'
import Router from 'vue-router'
import { mockComponent } from './hoc'
import { siteData as i18nSiteData } from './.temp/siteData-i18n'
import { siteData as simpleSiteData } from './.temp/siteData-simple'
export function getRouter () {
return new Router()
}
export function getLocalVueByMode (mode) {
const localVue = createLocalVue()
localVue.use(Router)
// register global component
localVue.component('OutboundLink', mockComponent('outbound-link'))
// register page component in root route.
localVue.component(i18nSiteData.pages[0].key, mockComponent('page-component'))
localVue.component(simpleSiteData.pages[0].key, mockComponent('page-component'))
// data mixin
if (mode === 'i18n') {
localVue.mixin(dataMixin(i18nSiteData))
} else {
localVue.mixin(dataMixin(simpleSiteData))
}
return localVue
}
export function modeTestRunner (description, testFn, modes = ['simple', 'i18n']) {
if (!Array.isArray(modes)) {
modes = [modes]
}
modes.forEach(mode => {
describe(description, () => {
testFn(mode, getLocalVueByMode(mode))
})
})
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册