1
0
mirror of https://github.com/kremalicious/portfolio.git synced 2024-11-15 01:25:25 +01:00

fix tests

This commit is contained in:
Matthias Kretschmann 2019-11-17 16:03:57 +01:00
parent 83d62c109b
commit 21cb1a1ffa
Signed by: m
GPG Key ID: 606EEEF3C479A91F
6 changed files with 106 additions and 30 deletions

View File

@ -18,8 +18,8 @@
- [⛵️ Lighthouse score](#-lighthouse-score)
- [💍 One data file to rule all pages](#-one-data-file-to-rule-all-pages)
- [🐱 GitHub repositories](#-github-repositories)
- 🗂 JSON Resume](#-json-resume)
- [💅 Theme switcher](#-theme-switcher)
- [🗂 JSON Resume](#-json-resume)
- [🏆 SEO component](#-seo-component)
- [📇 Client-side vCard creation](#-client-side-vcard-creation)
- [💫 Page transitions](#-page-transitions)
@ -66,6 +66,16 @@ If you want to know how, have a look at the respective components:
- [`content/repos.yml`](content/repos.yml)
- [`src/components/molecules/Repository.jsx`](src/components/molecules/Repository.jsx)
### 🗂 JSON Resume
Resume page based on [JSON Resume](https://jsonresume.org) standard. Most site metadata and social profiles are defined in [`content/resume.json`](content/resume.json) and used throughout the site.
If you want to know how, have a look at the respective components:
- [`content/resume.json`](content/resume.json)
- [`src/pages/resume/index.jsx`](src/pages/resume/index.jsx)
- [`src/hooks/use-resume.js`](src/hooks/use-resume.js)
### 💅 Theme switcher
Includes a theme switcher which allows user to toggle between a light and a dark theme. Switching between them also happens automatically based on user's local sunset and sunrise times. Uses Cloudflare's geo location HTTP header functionality.
@ -77,16 +87,6 @@ If you want to know how, have a look at the respective components:
- [`src/components/molecules/ThemeSwitch.jsx`](src/components/molecules/ThemeSwitch.jsx)
- [`src/hooks/use-dark-mode.jsx`](src/hooks/use-dark-mode.jsx)
### 🗂 JSON Resume
Resume page based on [JSON Resume](https://jsonresume.org) standard. Most metadata and social profiles are defined in [`content/resume.json`](content/resume.json) and used throughout the site.
If you want to know how, have a look at the respective components:
- [`content/resume.json`](content/resume.json)
- [`src/pages/resume.jsx`](src/pages/resume.jsx)
- [`src/hooks/use-resume.js`](src/hooks/use-resume.js)
### 🏆 SEO component
Includes a SEO component which automatically switches all required `meta` tags for search engines, Twitter Cards, and Facebook OpenGraph tags based on the browsed route/page.

63
package-lock.json generated
View File

@ -3042,6 +3042,14 @@
}
}
},
"@mapbox/hast-util-table-cell-style": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/@mapbox/hast-util-table-cell-style/-/hast-util-table-cell-style-0.1.3.tgz",
"integrity": "sha512-QsEsh5YaDvHoMQ2YHdvZy2iDnU3GgKVBTcHf6cILyoWDZtPSdlG444pL/ioPYO/GpXSfODBb9sefEetfC4v9oA==",
"requires": {
"unist-util-visit": "^1.3.0"
}
},
"@mikaelkristiansson/domready": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/@mikaelkristiansson/domready/-/domready-1.0.9.tgz",
@ -12455,6 +12463,19 @@
"minimalistic-assert": "^1.0.1"
}
},
"hast-to-hyperscript": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/hast-to-hyperscript/-/hast-to-hyperscript-7.0.4.tgz",
"integrity": "sha512-vmwriQ2H0RPS9ho4Kkbf3n3lY436QKLq6VaGA1pzBh36hBi3tm1DO9bR+kaJIbpT10UqaANDkMjxvjVfr+cnOA==",
"requires": {
"comma-separated-tokens": "^1.0.0",
"property-information": "^5.3.0",
"space-separated-tokens": "^1.0.0",
"style-to-object": "^0.2.1",
"unist-util-is": "^3.0.0",
"web-namespaces": "^1.1.2"
}
},
"hast-util-is-element": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-1.0.3.tgz",
@ -13158,6 +13179,11 @@
"prop-types": "^15.5.10"
}
},
"inline-style-parser": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz",
"integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q=="
},
"inquirer": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.0.tgz",
@ -20679,6 +20705,14 @@
"react-is": "^16.8.1"
}
},
"property-information": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/property-information/-/property-information-5.3.0.tgz",
"integrity": "sha512-IslotQn1hBCZDY7SaJ3zmCjVea219VTwmOk6Pu3z9haU9m4+T8GwaDubur+6NMHEU+Fjs/6/p66z6QULPkcL1w==",
"requires": {
"xtend": "^4.0.1"
}
},
"proto-list": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
@ -21531,6 +21565,11 @@
}
}
},
"remark-breaks": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/remark-breaks/-/remark-breaks-1.0.3.tgz",
"integrity": "sha512-ip5hvJE8vsUJCGfgHaEJbf/JfO6KTZV+NBG68AWkEMhrjHW3Qh7EorED41mCt0FFSTrUDeRiNHovKO7cqgPZmw=="
},
"remark-html": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/remark-html/-/remark-html-10.0.0.tgz",
@ -21564,6 +21603,17 @@
"xtend": "^4.0.1"
}
},
"remark-react": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/remark-react/-/remark-react-6.0.0.tgz",
"integrity": "sha512-5g73p8ZuqKoSdKByEf6IbXtVaHnbSEV0aamhIIqpzeNvj1wWDPX0USSPs4Gf3ZAsQIehIp6QiqJIbbXpq74bug==",
"requires": {
"@mapbox/hast-util-table-cell-style": "^0.1.3",
"hast-to-hyperscript": "^7.0.0",
"hast-util-sanitize": "^2.0.0",
"mdast-util-to-hast": "^6.0.0"
}
},
"remark-stringify": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-7.0.4.tgz",
@ -23631,6 +23681,14 @@
"integrity": "sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI=",
"dev": true
},
"style-to-object": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.2.3.tgz",
"integrity": "sha512-1d/k4EY2N7jVLOqf2j04dTc37TPOv/hHxZmvpg8Pdh8UYydxeu/C1W1U4vD8alzf5V2Gt7rLsmkr4dxAlDm9ng==",
"requires": {
"inline-style-parser": "0.1.1"
}
},
"style-value-types": {
"version": "3.1.7",
"resolved": "https://registry.npmjs.org/style-value-types/-/style-value-types-3.1.7.tgz",
@ -25715,6 +25773,11 @@
"defaults": "^1.0.3"
}
},
"web-namespaces": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.3.tgz",
"integrity": "sha512-r8sAtNmgR0WKOKOxzuSgk09JsHlpKlB+uHi937qypOu3PZ17UxPrierFKDye/uNHjNTTEshu5PId8rojIPj/tA=="
},
"webidl-conversions": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",

View File

@ -15,7 +15,12 @@ import {
FileText,
Key,
Image,
Mail
Mail,
MapPin,
Globe,
Briefcase,
Award,
BookOpen
} from 'react-feather'
import { ReactComponent as Dribbble } from '../../images/dribbble.svg'
import styles from './Icon.module.scss'
@ -41,7 +46,12 @@ const Icon = ({ name, ...props }) => {
FileText,
Key,
Image,
Mail
Mail,
MapPin,
Globe,
Briefcase,
Award,
BookOpen
}
const IconMapped = components[name]

View File

@ -39,21 +39,19 @@ export default function Vcard() {
export const init = async meta => {
// first, convert the avatar to base64, then construct all vCard elements
const dataUrl = await toDataURL(meta.photoSrc, 'image/jpeg')
const vcard = await constructVcard(dataUrl, meta)
downloadVcard(vcard, meta)
}
const vcard = await constructVcard(meta, dataUrl)
// Construct the download from a blob of the just constructed vCard,
// and save it to user's file system
export const downloadVcard = (vcard, meta) => {
const { addressbook } = meta
const name = addressbook.split('/').join('')
const blob = new Blob([vcard], { type: 'text/x-vcard' })
const blob = new Blob([vcard], {
type: 'text/x-vcard'
})
// save it to user's file system
saveAs(blob, name)
}
export const constructVcard = async (dataUrl, meta) => {
export const constructVcard = async meta => {
const contact = new vCard()
const blog = meta.profiles.filter(({ network }) => network === 'Blog')[0].url
const twitter = meta.profiles.filter(
@ -82,7 +80,7 @@ export const constructVcard = async (dataUrl, meta) => {
// Helper function to create base64 string from avatar image
// without the need to read image file from file system
export const toDataURL = async (photoSrc, outputFormat) => {
export async function toDataURL(photoSrc, outputFormat) {
const img = new Image()
img.crossOrigin = 'Anonymous'
img.src = photoSrc

View File

@ -1,7 +1,16 @@
import React from 'react'
import { render, fireEvent, waitForElement } from '@testing-library/react'
import Vcard, { constructVcard, toDataURL, init } from './Vcard'
import data from '../../../jest/__fixtures__/meta.json'
import meta from '../../../jest/__fixtures__/meta.json'
import resume from '../../../jest/__fixtures__/resume.json'
const metaMock = {
...meta.metaYaml,
name: resume.contentJson.basics.name,
label: resume.contentJson.basics.label,
email: resume.contentJson.basics.email,
profiles: [...resume.contentJson.basics.profiles]
}
describe('Vcard', () => {
beforeEach(() => {
@ -21,15 +30,12 @@ describe('Vcard', () => {
})
it('combined vCard download process finishes', async () => {
await init(data.metaYaml)
await init(metaMock)
expect(global.URL.createObjectURL).toHaveBeenCalledTimes(1)
})
it('vCard can be constructed', async () => {
const vcard = await constructVcard(
'data:image/jpeg;base64,00',
data.metaYaml
)
const vcard = await constructVcard(metaMock, 'data:image/jpeg;base64,00')
expect(vcard).toBeDefined()
})

View File

@ -49,7 +49,6 @@ const query = graphql`
startDate
endDate
summary
highlights
}
awards {
title