今回はTestcafeを用いてmetaやOGP情報を取得してjsonに吐き出す処理についてです。
Testcafeでmeta titileやdisctiptionなどを取得するには、クライアント側から任意のシリアライズ可能な値を返すことができるClientFunction
と呼ばれるクライアント関数を使用します。
import { ClientFunction } from 'testcafe';
const testUrl = 'https://example.com/'
// url path
export const getUrl = ClientFunction(() => location.pathname);
// meta titile
export const getTitle = ClientFunction(() => document.title);
// title文字数
export const getTitleLength = ClientFunction(() => document.title.length);
// meta description
export const getDesc = ClientFunction(() => {
const description = document.getElementsByName('description')[0]
if (description === undefined || description.content === '') return null
return description.content
})
// meta description文字数
export const getDescLength = ClientFunction(() => {
const description = document.getElementsByName('description')[0]
if (description === undefined || description.content === '') return null
return description.content.length
})
// meta keyword
export const getKeyword = ClientFunction(() => {
const keyword = document.getElementsByName('keyword')[0]
if (keyword === undefined || keyword.content === '') return null
return keyword.content
})
// meta keyword個数
export const getKeywordLength = ClientFunction(() => {
const keyword = document.getElementsByName('keyword')[0]
if (keyword === undefined || keyword.content === '') return null
return keyword.content.split(',').length
})
// og:title
export const getOgTitle = ClientFunction(() => {
const ogTitle = document.querySelector("meta[property='og:title']")
if (ogTitle === undefined || ogTitle.content === '') return null
return ogTitle.content
})
// og:url
export const getOgUrl = ClientFunction(() => {
const ogUrl = document.querySelector("meta[property='og:url']")
if (ogUrl === undefined || ogUrl.content === '') return null
return ogUrl.content
})
// og:image
export const getOgImg = ClientFunction(() => {
const ogImg = document.querySelector("meta[property='og:image']")
if (ogImg === undefined || ogImg.content === '') return null
return ogImg.content
})
// og:site_name
export const getOgSiteName = ClientFunction(() => {
const ogOgSiteName = document.querySelector("meta[property='og:site_name']")
if (ogOgSiteName === undefined || ogOgSiteName.content === '') return null
return ogOgSiteName.content
})
// og:description
export const getOgDesc = ClientFunction(() => {
const ogDesc = document.querySelector("meta[property='og:description']")
if (ogDesc === undefined || ogDesc.content === '') return null
return ogDesc.content
})
// meta robots
export const getRobots = ClientFunction(() => {
const robots = document.getElementsByName('robots')[0]
if (robots === undefined || robots.content === '') return null
return robots.content
})
// canonical
export const getCanonicalUrl = ClientFunction(() => {
const links = document.getElementsByTagName('link')
for (var i = 0; i < links.length; i++) {
if (links[i].rel.toLowerCase() == 'canonical') {
return links[i].href
}
}
return null
})
そしてawait
で呼び出して実行します。
今回はスクリーンショットを撮るテストを開始する前に処理が行われるようTest.before
メソッドを使いましたが、Test.before
を使わずテストとして書いていくのもOKです!
import { ClientFunction } from 'testcafe'
const common = require('../common')
const { testUrl, getUrl, getTitle, getTitleLength, getDesc, getDescLength, getKeyword, getKeywordLength, getOgTitle, getOgUrl, getOgImg, getOgSiteName, getOgDesc, getCanonicalUrl, getRobots } = common;
const screenShot = (testName, testUrl) => {
fixture(testName).page(testUrl)
test
.before( async t => {
const pageUrl = await getUrl();
const pageTitle = await getTitle();
const pageTitleLength = await getTitleLength();
const pageDesc = await getDesc();
const pageDescLength = await getDescLength();
const pageKeyword = await getKeyword();
const pageKeywordLength = await getKeywordLength();
const OgTitle = await getOgTitle();
const OgUrl = await getOgUrl();
const OgImg = await getOgImg();
const OgSiteName = await getOgSiteName();
const OgDesc = await getOgDesc();
const canonicalUrl = await getCanonicalUrl();
const robotsContent = await getRobots();
})
(testName, async t => {
//スクリーンショットの処理
});
}
screenShot('top', `${testUrl}`)
これでtitileとdiscription etc...を取得することができました!
次に取得した値をjsonに吐き出す処理を書いていきます。
import { ClientFunction } from 'testcafe'
const fs = require('fs')
const common = require('../common')
const { testUrl, getUrl, getTitle, getTitleLength, getDesc, getDescLength, getKeyword, getKeywordLength, getOgTitle, getOgUrl, getOgImg, getOgSiteName, getOgDesc, getCanonicalUrl, getRobots } = common;
const masterData = []
const screenShot = (testName, testUrl) => {
fixture(testName).page(testUrl)
test
.before( async t => {
const pageUrl = await getUrl();
const pageTitle = await getTitle();
const pageTitleLength = await getTitleLength();
const pageDesc = await getDesc();
const pageDescLength = await getDescLength();
const pageKeyword = await getKeyword();
const pageKeywordLength = await getKeywordLength();
const OgTitle = await getOgTitle();
const OgUrl = await getOgUrl();
const OgImg = await getOgImg();
const OgSiteName = await getOgSiteName();
const OgDesc = await getOgDesc();
const canonicalUrl = await getCanonicalUrl();
const robotsContent = await getRobots();
const data = {
page: pageUrl,
title: [
{
text: pageTitle,
'最大29文字程度': pageTitleLength ? pageTitleLength <= '29' : pageTitleLength >= '29'
}
],
description: [
{
text: pageDesc,
'最大110字程度': pageDescLength ? pageDescLength <= '110' : pageDescLength >= '110'
}
],
keyword: [
{
text: pageKeyword,
'5〜6個程度': pageKeywordLength ? pageKeywordLength <= '6' : pageKeywordLength >= '6'
}
],
'og:title': OgTitle,
'og:url': OgUrl,
'og:image': OgImg,
'og:site_name': OgSiteName,
'og:description': OgDesc,
canonical: canonicalUrl,
robots: robotsContent
}
masterData.push(data)
let str = JSON.stringify({meta: masterData}, null, ' ')
fs.writeFileSync('./screenshots/data.json', str);
})
(testName, async t => {
//スクリーンショットの処理
});
}
screenShot('top', `${testUrl}`)
まずconst masterData = []
で空の配列を作成し、pushで値を入れ込んでいきます。
そしてJSON.stringify
でJSON文字列に変換し、fs.writeFileSync
で指定したjsonに書き込んで終了です!
生成されたjsonが↓こちら。
{
"meta": [
{
"page": "/",
"title": [
{
"text": "株式会社Sample",
"最大29文字程度": true
}
],
"description": [
{
"text": "株式会社Sampleのdescriptionが入ります。",
"最大110字程度": true
}
],
"keyword": [
{
"text": "株式会社Sample,サンプル,sample,北海道,東京,大阪,福岡",
"5〜6個程度": false
}
],
"og:title": "株式会社Sample",
"og:url": "https://example.com/",
"og:image": "https://example.com/img/ogp.png?1603865417442",
"og:site_name": "株式会社Sample",
"og:description": "株式会社Sampleのog:descriptionが入ります。",
"canonical": "",
"robots": null
}
]
}
綺麗に生成することができました!
ちなみにtitileやdescriptionなどにはSEOに最適とされる文字数があるので、設定した文字数を超えている場合はfalse
、設定値に収まる場合はtrue
を。robotsなどタグ自体がないものはnullを返すようにしています。