mirror of
https://github.com/tenrok/vue-meta.git
synced 2026-06-21 10:20:34 +03:00
test: add e2e tests
This commit is contained in:
+89
-52
@@ -1,79 +1,116 @@
|
||||
import Browser from '../utils/browser'
|
||||
import { buildFixture } from '../utils/build'
|
||||
/**
|
||||
* @jest-environment node
|
||||
*/
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import env from 'node-env-file'
|
||||
import { browser as startBrowser } from 'tib'
|
||||
|
||||
const browser = new Browser()
|
||||
const browserString = process.env.BROWSER_STRING || 'puppeteer/core'
|
||||
|
||||
describe('basic browser with ssr page', () => {
|
||||
let page = null
|
||||
let url
|
||||
let html
|
||||
describe(browserString, () => {
|
||||
let browser
|
||||
let page
|
||||
const folder = path.resolve(__dirname, '..', 'fixtures/basic/.vue-meta/')
|
||||
|
||||
beforeAll(async () => {
|
||||
const fixture = await buildFixture('basic')
|
||||
url = fixture.url
|
||||
html = fixture.html
|
||||
if (browserString.includes('browserstack') && browserString.includes('local')) {
|
||||
const envFile = path.resolve(__dirname, '..', '..', '.env-browserstack')
|
||||
if (fs.existsSync(envFile)) {
|
||||
env(envFile)
|
||||
}
|
||||
}
|
||||
|
||||
await browser.start({
|
||||
// slowMo: 50,
|
||||
// headless: false
|
||||
browser = await startBrowser(browserString, {
|
||||
BrowserStackLocal: { folder },
|
||||
extendPage(page) {
|
||||
return {
|
||||
async navigate(path) {
|
||||
// IMPORTANT: use (arrow) function with block'ed body
|
||||
// see: https://github.com/tunnckoCoreLabs/parse-function/issues/179
|
||||
await page.runAsyncScript((path) => {
|
||||
return new Promise((resolve) => {
|
||||
const oldTitle = document.title
|
||||
|
||||
// local firefox has sometimes not updated the title
|
||||
// even when the DOM is supposed to be fully updated
|
||||
const waitTitleChanged = function () {
|
||||
setTimeout(function () {
|
||||
if (oldTitle !== document.title) {
|
||||
resolve()
|
||||
} else {
|
||||
waitTitleChanged()
|
||||
}
|
||||
}, 50)
|
||||
}
|
||||
|
||||
window.$vueMeta.$once('routeChanged', waitTitleChanged)
|
||||
window.$vueMeta.$router.push(path)
|
||||
})
|
||||
}, path)
|
||||
},
|
||||
routeData() {
|
||||
return page.runScript(() => ({
|
||||
path: window.$vueMeta.$route.path,
|
||||
query: window.$vueMeta.$route.query
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// Stop browser
|
||||
afterAll(async () => {
|
||||
if (page) await page.close()
|
||||
await browser.close()
|
||||
if (browser) {
|
||||
await browser.close()
|
||||
}
|
||||
})
|
||||
|
||||
test('validate ssr', () => {
|
||||
const htmlTag = html.match(/<html([^>]+)>/)[0]
|
||||
expect(htmlTag).toContain('data-vue-meta-server-rendered')
|
||||
expect(htmlTag).toContain(' lang="en" ')
|
||||
expect(htmlTag).toContain(' amp ')
|
||||
expect(htmlTag).not.toContain('allowfullscreen')
|
||||
expect(html.match(/<title[^>]*>(.*?)<\/title>/)[1]).toBe('Home | Vue Meta Test')
|
||||
expect(html.match(/<meta/g).length).toBe(2)
|
||||
expect(html.match(/<meta/g).length).toBe(2)
|
||||
test('open page', async () => {
|
||||
const webPath = '/index.html'
|
||||
|
||||
const re = /<(no)?script[^>]+type="application\/ld\+json"[^>]*>(.*?)</g
|
||||
const sanitizeCheck = []
|
||||
let match
|
||||
while ((match = re.exec(html))) {
|
||||
sanitizeCheck.push(match[2])
|
||||
let url
|
||||
if (browser.getLocalFolderUrl) {
|
||||
url = browser.getLocalFolderUrl(webPath)
|
||||
} else {
|
||||
url = `file://${path.join(folder, webPath)}`
|
||||
}
|
||||
|
||||
expect(sanitizeCheck.length).toBe(3)
|
||||
expect(() => JSON.parse(sanitizeCheck[0])).not.toThrow()
|
||||
expect(() => JSON.parse(sanitizeCheck[1])).toThrow()
|
||||
expect(() => JSON.parse(sanitizeCheck[2])).not.toThrow()
|
||||
})
|
||||
|
||||
test('Open /', async () => {
|
||||
page = await browser.page(url)
|
||||
|
||||
expect(await page.$attr('html', 'data-vue-meta-server-rendered')).toBe(null)
|
||||
expect(await page.$attr('html', 'lang')).toBe('en')
|
||||
expect(await page.$attr('html', 'amp')).toBe('')
|
||||
expect(await page.$attr('html', 'allowfullscreen')).toBe(null)
|
||||
expect(await page.$attr('head', 'test')).toBe('true')
|
||||
expect(await page.$text('h1')).toBe('Basic')
|
||||
expect(await page.$text('title')).toBe('Home | Vue Meta Test')
|
||||
expect(await page.$$eval('meta', metas => metas.length)).toBe(2)
|
||||
expect(await page.getAttribute('html', 'data-vue-meta-server-rendered')).toBe(null)
|
||||
expect(await page.getAttribute('html', 'lang')).toBe('en')
|
||||
expect(await page.getAttribute('html', 'amp')).toBe('')
|
||||
expect(await page.getAttribute('html', 'allowfullscreen')).toBe(null)
|
||||
expect(await page.getAttribute('head', 'test')).toBe('true')
|
||||
expect(await page.getText('h1')).toBe('Basic')
|
||||
expect(await page.getText('title')).toBe('Home | Vue Meta Test')
|
||||
expect(await page.getElementCount('meta')).toBe(2)
|
||||
|
||||
let sanitizeCheck = await page.$$text('script')
|
||||
sanitizeCheck.push(...(await page.$$text('noscript')))
|
||||
let sanitizeCheck = await page.getTexts('script')
|
||||
sanitizeCheck.push(...(await page.getTexts('noscript')))
|
||||
sanitizeCheck = sanitizeCheck.filter(v => !!v)
|
||||
|
||||
expect(sanitizeCheck.length).toBe(3)
|
||||
expect(() => JSON.parse(sanitizeCheck[0])).not.toThrow()
|
||||
expect(() => JSON.parse(sanitizeCheck[1])).not.toThrow()
|
||||
// TODO: check why this doesnt Throw when Home is dynamic loaded
|
||||
// (but that causes hydration error)
|
||||
expect(() => JSON.parse(sanitizeCheck[1])).toThrow()
|
||||
expect(() => JSON.parse(sanitizeCheck[2])).not.toThrow()
|
||||
})
|
||||
|
||||
test('/about', async () => {
|
||||
const { hook } = await page.vueMeta.navigate('/about', false)
|
||||
await hook
|
||||
expect(await page.$text('title')).toBe('About')
|
||||
expect(await page.$$eval('meta', metas => metas.length)).toBe(1)
|
||||
try {
|
||||
await page.navigate('/about', false)
|
||||
} catch (e) {
|
||||
if (e.constructor.name !== 'ScriptTimeoutError') {
|
||||
throw e
|
||||
} else {
|
||||
console.warn(e) // eslint-disable-line no-console
|
||||
}
|
||||
}
|
||||
|
||||
expect(await page.getText('title')).toBe('About')
|
||||
expect(await page.getElementCount('meta')).toBe(1)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { buildFixture } from '../utils/build'
|
||||
|
||||
describe('basic browser with ssr page', () => {
|
||||
let html
|
||||
|
||||
beforeAll(async () => {
|
||||
const fixture = await buildFixture('basic')
|
||||
html = fixture.html
|
||||
})
|
||||
|
||||
test('validate ssr', () => {
|
||||
const htmlTag = html.match(/<html([^>]+)>/)[0]
|
||||
expect(htmlTag).toContain('data-vue-meta-server-rendered')
|
||||
expect(htmlTag).toContain(' lang="en" ')
|
||||
expect(htmlTag).toContain(' amp ')
|
||||
expect(htmlTag).not.toContain('allowfullscreen')
|
||||
expect(html.match(/<title[^>]*>(.*?)<\/title>/)[1]).toBe('Home | Vue Meta Test')
|
||||
expect(html.match(/<meta/g).length).toBe(2)
|
||||
expect(html.match(/<meta/g).length).toBe(2)
|
||||
|
||||
const re = /<(no)?script[^>]+type="application\/ld\+json"[^>]*>(.*?)</g
|
||||
const sanitizeCheck = []
|
||||
let match
|
||||
while ((match = re.exec(html))) {
|
||||
sanitizeCheck.push(match[2])
|
||||
}
|
||||
|
||||
expect(sanitizeCheck.length).toBe(3)
|
||||
expect(() => JSON.parse(sanitizeCheck[0])).not.toThrow()
|
||||
expect(() => JSON.parse(sanitizeCheck[1])).toThrow()
|
||||
expect(() => JSON.parse(sanitizeCheck[2])).not.toThrow()
|
||||
})
|
||||
})
|
||||
Vendored
+9
-5
@@ -8,13 +8,17 @@
|
||||
|
||||
<script>
|
||||
export default {
|
||||
metaInfo: {
|
||||
meta: [
|
||||
{ vmid: 'charset', charset: 'utf-8' }
|
||||
]
|
||||
metaInfo() {
|
||||
return {
|
||||
meta: [
|
||||
{ vmid: 'charset', charset: 'utf-8' }
|
||||
],
|
||||
afterNavigation: () => {
|
||||
this.$emit('routeChanged')
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$router.afterEach((to, from) => this.$emit('routeChanged', to, from))
|
||||
window.$vueMeta = this
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -1,9 +1,9 @@
|
||||
import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
import Home from './views/home.vue'
|
||||
|
||||
Vue.use(Router)
|
||||
|
||||
const Home = () => import('./views/home.vue')
|
||||
const Post = () => import('./views/about.vue')
|
||||
|
||||
export default function createRouter() {
|
||||
|
||||
+25
-2
@@ -38,6 +38,7 @@ export async function buildFixture(fixture, config = {}) {
|
||||
await fs.remove(webpackConfig.output.path)
|
||||
|
||||
// run webpack
|
||||
process.env.NODE_ENV = 'test'
|
||||
const webpackStats = await webpackRun(webpackConfig)
|
||||
|
||||
// for test debugging
|
||||
@@ -73,6 +74,7 @@ export function createWebpackConfig(config = {}) {
|
||||
|
||||
return {
|
||||
mode: 'development',
|
||||
devtool: 'none',
|
||||
output: {
|
||||
path: path.join(path.dirname(config.entry), publicPath),
|
||||
filename: '[name].js',
|
||||
@@ -81,7 +83,22 @@ export function createWebpackConfig(config = {}) {
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{ test: /\.js$/, exclude: /node_modules/, use: 'babel-loader' },
|
||||
{
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules/,
|
||||
use: {
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
presets: [
|
||||
['@babel/preset-env', {
|
||||
useBuiltIns: 'usage',
|
||||
corejs: 'core-js@2',
|
||||
targets: { ie: 9, safari: '5.1' }
|
||||
}]
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{ test: /\.vue$/, use: 'vue-loader' }
|
||||
]
|
||||
},
|
||||
@@ -102,7 +119,13 @@ export function createWebpackConfig(config = {}) {
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
new VueLoaderPlugin()
|
||||
new VueLoaderPlugin(),
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
// make sure our simple polyfills are enabled
|
||||
'NODE_ENV': '"test"'
|
||||
}
|
||||
})
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
jest.useFakeTimers()
|
||||
jest.setTimeout(15000)
|
||||
jest.setTimeout(30000)
|
||||
|
||||
Reference in New Issue
Block a user