Skip to content

Commit

Permalink
Add contentful based top banner (cypress-io#1911)
Browse files Browse the repository at this point in the history
* data fetch && swig && styles

* banners actualization script

* finish (?)

* finish (?)

* remove "extends" from eslint settings

* remove sensitive info

* update hexo index file

* banner padding fix

* remove Promise.protoype.finally() from hexo index script

* Contentful driven banners, parsed dynamically:
Hexo index.js && data fetch && swig && styles && banners_actualization script

* add cypress test for banners

* docs update v1

* Fix toc width so that it doesn't create a horizontal scrollbar on smaller heights screen.

* package-lock

* just a few tweaks to the README instructions

* fixed conflict issue from package.json merge
  • Loading branch information
TonySynenko authored and amirrustam committed Jul 31, 2019
1 parent c419788 commit c336823
Show file tree
Hide file tree
Showing 19 changed files with 442 additions and 55 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ themes/cypress/source/fonts/vendor/

cypress/screenshots
cypress/videos

# Dynamically parsed data
source/_data/banners.yml
31 changes: 31 additions & 0 deletions cypress/integration/contentful_banners_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const YAML = require('yamljs')
const emojiStrip = require('emoji-strip')

const allBannersYaml = 'source/_data/banners.yml'

describe('Contentful driven banners', () => {
it('displays all current banners with proper info', function () {
cy.readFile(allBannersYaml)
.then((yamlString) => YAML.parse(yamlString.replace(/\\u[\dA-F]{8}/gi, '')))
.then((banners) => {
if (typeof banners === 'undefined' || !banners || !banners.length) return this.skip()

cy.visit('/')

cy.get('#header .top-banners_item')
.each((banner, i) => {
const text = banner.children('.top-banners_item--body').html().trim()
const { startDate, endDate } = banner.data()
const btn = banner.children('.call-to-action')
const btnText = btn.text().trim()
const btnLink = btn.attr('href')

expect(emojiStrip(text), `Banner #${i + 1} text is proper`).to.eq(banners[i].text.replace(/\r?\n|\r/g, ' '))
expect(startDate, `Banner #${i + 1} startDate is proper`).to.eq(banners[i].startDate)
expect(endDate, `Banner #${i + 1} endDate is proper`).to.eq(banners[i].endDate)
expect(btnText, `Banner #${i + 1} call-to-action text is proper`).to.eq(banners[i].buttonText.trim())
expect(btnLink, `Banner #${i + 1} call-to-action link is proper`).to.eq(banners[i].buttonLink)
})
})
})
})
57 changes: 51 additions & 6 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ process.on('unhandledRejection', function (reason, p) {
const Hexo = require('hexo')
const chalk = require('chalk')
const minimist = require('minimist')
const Contentful = require('contentful')
const moment = require('moment')
const yaml = require('js-yaml')
const fs = require('fs')
const { documentToHtmlString } = require('@contentful/rich-text-html-renderer')

// these are the args like --port
const args = minimist(process.argv.slice(2))
Expand Down Expand Up @@ -86,17 +91,57 @@ function initHexo () {
console.log('in environment %s site url is %s', env, url)
hexo.config.url = url

// set this on both our process + hexo
// set this on both our process + Hexo
process.env.NODE_ENV = hexo.env.NODE_ENV = env

console.log('NODE_ENV is:', chalk.cyan(env))

return hexo.init()
.then(() => {
return hexo.call(cmd, args)
return new Promise((resolve, reject) => {
const space = hexo.env.GATSBY_CONTENTFUL_SPACE_ID || process.env.GATSBY_CONTENTFUL_SPACE_ID
const accessToken = hexo.env.GATSBY_CONTENTFUL_ACCESS_TOKEN || process.env.GATSBY_CONTENTFUL_ACCESS_TOKEN

if (typeof space === 'undefined' || typeof accessToken === 'undefined') {
return reject({
message: 'No Contentful space variables.',
})
}

return Contentful.createClient({ space, accessToken })
.getEntries({ content_type: 'topBanner' })
.then(({ items }) => {
const data = items.reduce((filtered, option) => {
if (moment(option.fields.endDate).isSameOrAfter(moment())) {
filtered.push({ ...option.fields, text: documentToHtmlString(option.fields.text) })
}

return filtered
}, [])

fs.writeFile(
`${__dirname}/source/_data/banners.yml`,
yaml.safeDump(data),
(error) => {
// log if writeFile ends with error, but don't block hexo init process
if (error) {
console.warn(error)

return reject(error)
}

return resolve()
},
)
})
})
// start Hexo
.then(() => hexo.init().then(() => hexo.call(cmd, args)))
.catch((error) => {
// log error object
console.error(error)

// but start Hexo anyway
return hexo.init().then(() => hexo.call(cmd, args))
})

}

initHexo()

99 changes: 99 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
"cypress": "3.4.1",
"dependency-check": "3.4.1",
"deps-ok": "1.4.1",
"emoji-strip": "1.0.1",
"eslint": "6.1.0",
"eslint-plugin-cypress": "2.6.0",
"eslint-plugin-cypress-dev": "2.1.0",
Expand Down Expand Up @@ -128,7 +129,9 @@
"yamljs": "0.3.0"
},
"dependencies": {
"@contentful/rich-text-html-renderer": "13.1.0",
"check-more-types": "2.24.0",
"contentful": "7.8.2",
"debug": "4.1.1",
"docsearch.js": "2.6.3",
"font-awesome": "4.7.0",
Expand All @@ -142,9 +145,11 @@
"hexo-renderer-marked": "0.3.2",
"hexo-renderer-scss": "1.2.0",
"hexo-server": "0.3.3",
"js-yaml": "3.13.1",
"lazy-ass": "1.6.0",
"lodash": "4.17.15",
"menuspy": "1.3.0",
"moment": "2.24.0",
"roboto-fontface": "0.10.0",
"scrollingelement": "1.5.2",
"yall": "github:malchata/yall.js#1c782f1ab7a0becb1a88fd6f3b260e55d5e213a2"
Expand Down
19 changes: 19 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,25 @@ please see our [Contributing Guideline](/CONTRIBUTING.md).

Cypress is [first time OSS contributor friendly](http://www.firsttimersonly.com/). See [these issues](https://github.com/cypress-io/cypress-documentation/labels/first-timers-only) to contribute in a meaningful way.

### Contentful driven data:

If you need any [Contentful](https://www.contentful.com/) driven data to be parsed before Hexo serve - you need to declare it Circle CI or/and bash. You may need [Contentful](https://www.contentful.com/) environment variables inside your machine or container:

- `GATSBY_CONTENTFUL_SPACE_ID`

[Contentful](https://www.contentful.com/) 12 digit key. You can find it (if you have granted access) in [Contentful](https://www.contentful.com/) acc:

Settings → API keys → Master → Space ID

- `GATSBY_CONTENTFUL_ACCESS_TOKEN`

[Contentful](https://www.contentful.com/) 64 digit token. You can find it (if you have granted access) in [Contentful](https://www.contentful.com/) acc:

Settings → API keys → Master → Content Delivery API - access token

P.S. If you don't have any of this - Hexo will build & serve as usual, but without any
[Contentful](https://www.contentful.com/) driven data.

## Deploying

See our [Deploy Guideline](DEPLOY.md).
Expand Down
5 changes: 5 additions & 0 deletions source/_data/banners.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
- startDate: '2019-07-17T14:00-05:00'
endDate: '2019-07-31T23:59-05:00'
text: "<p>\U0001F6A9Learn how to get complete code coverage with Cypress <a href=\"https://zoom.us/webinar/register/2115632233252/WN_bbV5ezckSMu9icH0KwuHuA\">on July 31st at 11AM PDT/2PM EDT</a> with Gleb Bahmutov and Amir Rustamzadeh <a href=\"https://zoom.us/webinar/register/2115632233252/WN_bbV5ezckSMu9icH0KwuHuA\"></a></p>"
buttonText: 'Register Now '
buttonLink: 'https://zoom.us/webinar/register/2115632233252/WN_bbV5ezckSMu9icH0KwuHuA'
2 changes: 1 addition & 1 deletion themes/cypress/layout/api-toc.swig
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div id="content-wrap" class="{{ page.containerClass }}">
<div id="content-wrap" class="{{ page.containerClass }}">
<div id="content" class="wrapper">
<div id="content-inner">
{{ partial('partial/sidebar') }}
Expand Down
11 changes: 9 additions & 2 deletions themes/cypress/layout/layout.swig
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,18 @@
{{ partial('partial/head') }}
<body>
{{ partial('partial/google-tag-manager-noscript')}}

<div id="container">
{{ partial('partial/header') }}
{{ body }}
{{ partial('partial/header', {}, { cache: true }) }}

<div>
{{ partial('partial/header', { className: 'header-top-hidden' }, { cache: true }) }}
{{ body }}
</div>
</div>

<div id="mobile-nav-dimmer"></div>

{{ partial('partial/mobile_nav') }}
{{ partial('partial/after_footer') }}
</body>
Expand Down
1 change: 1 addition & 0 deletions themes/cypress/layout/partial/after_footer.swig
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<!-- Scripts -->
<!-- build:js /js/application.js -->
{{ js('js/banners_actualization') }}
{{ js('js/global_variable') }}
{{ js('js/lang_select') }}
{{ js('js/vendor/scrollingelement') }}
Expand Down
13 changes: 13 additions & 0 deletions themes/cypress/layout/partial/banners.swig
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<div class="top-banners">
{% for banner in site.data.banners %}
<div class="top-banners_item" data-start-date="{{ banner.startDate }}" data-end-date="{{ banner.endDate }}">
<div class="top-banners_item--body">
{{ banner.text }}
</div>

<a class="top-banners_item--btn top-banners_item--btn-blue call-to-action" href="{{ banner.buttonLink }}">
{{ banner.buttonText || 'Get Started' }}
</a>
</div>
{% endfor %}
</div>
Loading

0 comments on commit c336823

Please sign in to comment.