Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pull] master from gatsbyjs:master #407

Merged
merged 14 commits into from
Feb 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ packages/gatsby-image/withIEPolyfill/index.js
packages/gatsby/cache-dir/commonjs/**/*
packages/gatsby-admin/public
packages/gatsby/gatsby-admin-public
packages/gatsby-codemods/transforms

packages/gatsby-source-wordpress/test-site/**
!packages/gatsby-source-wordpress/test-site/__tests__
Expand Down
61 changes: 43 additions & 18 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ module.exports = {
before: true,
after: true,
spyOn: true,
// These should be in scope but for some reason eslint can't see them
NodeJS: true,
JSX: true,
NodeRequire: true,
TimerHandler: true,
__PATH_PREFIX__: true,
__BASE_PATH__: true,
__ASSET_PREFIX__: true,
Expand All @@ -48,8 +53,10 @@ module.exports = {
"no-unused-vars": [
"warn",
{
varsIgnorePattern: "^_"
}
varsIgnorePattern: "^_",
argsIgnorePattern: "^_",
ignoreRestSiblings: true,
},
],
"consistent-return": ["error"],
"filenames/match-regex": ["error", "^[a-z-\\d\\.]+$", true],
Expand Down Expand Up @@ -93,7 +100,9 @@ module.exports = {
...TSEslint.configs.recommended.rules,
// We should absolutely avoid using ts-ignore, but it's not always possible.
// particular when a dependencies types are incorrect.
"@typescript-eslint/ban-ts-ignore": "warn",
"@typescript-eslint/ban-ts-comment": {
"ts-ignore": "allow-with-description",
},
// This rule is great. It helps us not throw on types for areas that are
// easily inferrable. However we have a desire to have all function inputs
// and outputs declaratively typed. So this let's us ignore the parameters
Expand All @@ -102,16 +111,38 @@ module.exports = {
"error",
{ ignoreParameters: true },
],
"@typescript-eslint/camelcase": [
"@typescript-eslint/ban-types": [
"error",
{
// This rule tries to ensure we use camelCase for all variables, properties
// functions, etc. However, it is not always possible to ensure properties
// are camelCase. Specifically we have `node.__gatsby_resolve` which breaks
// this rule. This allows properties to be whatever they need to be.
properties: "never",
// Allow unstable api's to use `unstable_`, which is easier to grep
allow: ["^unstable_"],
extendDefaults: true,
types: {
"{}": false,
object: {
fixWith: "Record<string, unknown>",
},
},
},
],
"@typescript-eslint/naming-convention": [
{
selector: "default",
format: ["camelCase"],
},
{ selector: "variable", format: ["camelCase", "UPPER_CASE"] },
{
selector: "parameter",
format: ["camelCase"],
leadingUnderscore: "allow",
prefix: ["unstable_", ""],
},
{
selector: "typeLike",
format: ["PascalCase"],
},
{
selector: "interface",
format: ["PascalCase"],
prefix: ["I"],
},
],
// This rule tries to prevent using `require()`. However in node code,
Expand All @@ -127,6 +158,7 @@ module.exports = {
// - baz: string;
// + baz: string
// }
"@typescript-eslint/no-extra-semi": false,
"@typescript-eslint/member-delimiter-style": [
"error",
{
Expand All @@ -135,13 +167,6 @@ module.exports = {
},
},
],
// This ensures all interfaces are named with an I as a prefix
// e.g.,
// interface IFoo {}
"@typescript-eslint/interface-name-prefix": [
"error",
{ prefixWithI: "always" },
],
"@typescript-eslint/no-empty-function": "off",
// This ensures that we always type the return type of functions
// a high level focus of our TS setup is typing fn inputs and outputs.
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/conceptual/gatsby-for-ecommerce.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ And with Gatsby’s pre-built integrations, it can pull data in from all of thes

E-commerce tends to have a number of specific requirements. When building a Gatsby site (or other decoupled/JAMStack site, for that matter) sourced from an ecommerce backend like Shopify, developers will typically have to think through a few additional touchpoints between the systems:

- **Persisting a cart across site pages and between sessions** (ie, if the user closes their browser and reopens it tomorrow, the items should still be there). This can handled either through local-storage or through the shopify-buy JS library.
- **Persisting a cart across site pages and between sessions** (ie, if the user closes their browser and reopens it tomorrow, the items should still be there). This can be handled either through local-storage or through the shopify-buy JS library.
- **Product search** can be done client-side if the SKU count is small enough to store all products in a global state. Alternatively, it can be handled through the e-commerce provider’s search features, or if those aren’t robust enough, a third-party search provider like Algolia.
- **Surfacing price adjustments** like tax, shipping, discounts/promos to the user while browsing the site. Different e-commerce solutions provide different levels of API access to these objects.
- **Handling checkout.** In order to comply with PCI regulations around storing credit card information, e-commerce providers typically exert strong control over the "buy" or "checkout" experience. Shopify requires all checkout flows using their platform to use their hosted checkout pages, though it's common to wrap them in a subdomain of the main site (eg the Gatsby/Shopify site [strivectin.com](strivectin.com] wraps a `myshopify.com` URL under a `shop.strivectin.com` URL for checkout).
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/debugging-html-builds.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ rendering.

```js:title=gatsby-node.js
exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
if (stage === "build-html") {
if (stage === "build-html" || stage === "develop-html") {
actions.setWebpackConfig({
module: {
rules: [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
function toggleLoadingIndicator(command) {
cy.then(() => fetch(`/___loading-indicator/${command}/`))
cy.wait(5000)
}

const refresh = async payload => {
return await fetch(`/__refresh/gatsby-source-query-on-demand-data/`, {
method: `POST`,
headers: {
"Content-Type": `application/json`,
},
body: payload ? JSON.stringify({ updateData: payload }) : undefined,
})
}

function assertIndicatorExists(doesExists) {
cy.get(`[data-gatsby-loading-indicator="root"]`, { timeout: 10000 }).should(
doesExists ? `exist` : `not.exist`
)
}

function assertIndicatorVisible(isVisible) {
cy.get(`[data-gatsby-loading-indicator="root"]`, { timeout: 10000 }).should(
isVisible ? `be.visible` : `not.be.visible`
)

cy.screenshot()
}

function runTests({
data,
sleep,
mode,
expectIndicatorEnabled,
expectIndicatorVisible,
}) {
// make sure we are not on a page with query
cy.visit(`/query-on-demand/no-query/`).waitForRouteChange()

// setup data for page with query
cy.then(() =>
refresh({
data,
sleep,
})
)

if (mode === `first-render`) {
cy.visit(`/query-on-demand/possibly-heavy-query/`)
} else if (mode === `client-navigation`) {
cy.findByTestId(`heavy-query-page-link`).click()
} else {
throw new Error(
`Unknown mode - should be one of ["first-render", "client-navigation"]`
)
}

// we wait for first render or for client side navigation to complete when we expect for loading indicator
// to show up (depending on test setup)
if (expectIndicatorEnabled) {
assertIndicatorExists(true)
assertIndicatorVisible(expectIndicatorVisible)
} else {
assertIndicatorExists(false)
}

cy.waitForRouteChange()

// once we finished first render or client side navigation - loading indicator should not be visible anymore (if it was before)
if (expectIndicatorEnabled) {
assertIndicatorExists(true)
assertIndicatorVisible(false)
} else {
assertIndicatorExists(false)
}

// making sure our test setup was correct and expect query result is rendered
cy.findByTestId(`query-data`).should(`have.text`, data)
}

describe(`Loading indicator`, () => {
before(async () => {
Cypress.config(`includeShadowDom`, true)
})

after(async () => {
toggleLoadingIndicator(`auto`)
})

// we disable showing loading indicator in cypress by default
// to not impact user tests - this is to make sure that's the case/catch regressions
describe(`Defaults in cypress env (doesn't show indicator)`, () => {
before(async () => {
toggleLoadingIndicator(`auto`)
})

describe(`Page with light/quick query doesn't show indicator`, () => {
const config = {
sleep: 0,
expectIndicatorEnabled: false,
expectIndicatorVisible: `doesn't matter because indicator should not be enabled`,
}

it(`Initial first render`, () => {
runTests({
...config,
data: `quick-first-render-with-disabled-indicator`,
mode: `first-render`,
})
})

it(`On navigation`, () => {
runTests({
...config,
data: `quick-client-navigation-with-disabled-indicator`,
mode: `client-navigation`,
})
})
})

describe(`Page with heavy/long running query doesn't show indicator (indicator is disabled)`, () => {
const config = {
sleep: 5000,
expectIndicatorEnabled: false,
expectIndicatorVisible: `doesn't matter because indicator should not be enabled`,
}

it(`Initial first render`, () => {
runTests({
...config,
data: `slow-first-render-with-disabled-indicator`,
mode: `first-render`,
})
})

it(`On navigation`, () => {
runTests({
...config,
data: `slow-client-navigation-with-disabled-indicator`,
mode: `client-navigation`,
})
})
})
})

describe(`With enabled loading indicator`, () => {
before(async () => {
toggleLoadingIndicator(`enable`)
})

describe(`Page with light/quick query doesn't show indicator`, () => {
const config = {
sleep: 0,
expectIndicatorEnabled: true,
expectIndicatorVisible: false,
}

it(`Initial first render`, () => {
runTests({
...config,
data: `quick-first-render-with-enabled-indicator`,
mode: `first-render`,
})
})

it(`On navigation`, () => {
runTests({
...config,
data: `quick-client-navigation-with-enabled-indicator`,
mode: `client-navigation`,
})
})
})

describe(`Page with heavy/long running query shows indicator`, () => {
const config = {
sleep: 5000,
expectIndicatorEnabled: true,
expectIndicatorVisible: true,
}

it(`Initial first render`, () => {
runTests({
...config,
data: `slow-first-render-with-enabled-indicator`,
mode: `first-render`,
})
})

it(`On navigation`, () => {
runTests({
...config,
data: `slow-client-navigation-with-enabled-indicator`,
mode: `client-navigation`,
})
})
})
})
})
2 changes: 1 addition & 1 deletion e2e-tests/development-runtime/cypress/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ Cypress.Commands.overwrite("visit", (orig, url, options = {}) => {
...options,
onBeforeLoad: win => {
if (options.onBeforeLoad) {
optiosn.onBeforeLoad(win)
options.onBeforeLoad(win)
}

cy.spy(win.console, "log").as(`hmrConsoleLog`)
Expand Down
1 change: 1 addition & 0 deletions e2e-tests/development-runtime/gatsby-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ module.exports = {
},
`gatsby-source-fake-data`,
`gatsby-source-pinc-data`,
`gatsby-source-query-on-demand-data`,
`gatsby-transformer-sharp`,
`gatsby-transformer-json`,
{
Expand Down
4 changes: 2 additions & 2 deletions e2e-tests/development-runtime/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"license": "MIT",
"scripts": {
"build": "gatsby build",
"develop": "cross-env CYPRESS_SUPPORT=y ENABLE_GATSBY_REFRESH_ENDPOINT=true gatsby develop",
"develop": "cross-env CYPRESS_SUPPORT=y ENABLE_GATSBY_REFRESH_ENDPOINT=true GATSBY_EXPERIMENTAL_QUERY_ON_DEMAND=y gatsby develop",
"serve": "gatsby serve",
"start": "npm run develop",
"format": "prettier --write \"src/**/*.js\"",
Expand All @@ -44,7 +44,7 @@
"start-server-and-test": "start-server-and-test develop http://localhost:8000 cy:run",
"start-server-and-debug": "start-server-and-test develop http://localhost:8000 cy:open",
"cy:open": "cypress open",
"cy:run": "(is-ci && cypress run --browser chrome --record) || cypress run --browser chrome"
"cy:run": "node ../../scripts/cypress-run-with-conditional-record-flag.js --browser chrome"
},
"devDependencies": {
"@testing-library/cypress": "^7.0.0",
Expand Down
Loading