-
Notifications
You must be signed in to change notification settings - Fork 10.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feature(gatsby): Add gatsby feedback (#21841)
* Create feedback command * progress with prompting heuristics * Finish heuristic * Finish hueristics and add tests * start hooking up feedback to cli commands * Finish implementation * Add an additional random selection heuristic * update message * add try/catch * Add documentation * Update docs/docs/feedback.md Co-Authored-By: LB <laurie@gatsbyjs.com> * Update docs/docs/feedback.md Co-Authored-By: LB <laurie@gatsbyjs.com> * fix feedback cli issues * rename files * fix lint * disable code to see if CI passes * try to run with more memory * pass tests Co-authored-by: LB <laurie@gatsbyjs.com>
- Loading branch information
1 parent
83ae63d
commit 096c28d
Showing
17 changed files
with
371 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
--- | ||
title: Gatsby CLI Feedback | ||
--- | ||
|
||
Gatsby users will be prompted every 3 months (at the most) to give feedback to Gatsby on our products and services. This feedback is incredibly valuable and will help us shape Gatsby. | ||
|
||
## How to opt-out | ||
|
||
Users may always opt-out from the feedback prompts with `gatsby feedback --disable` or by setting the environment variable `GATSBY_TELEMETRY_DISABLED` to `1` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import Configstore from "configstore" | ||
|
||
let config | ||
|
||
module.exports = () => { | ||
if (!config) { | ||
config = new Configstore( | ||
`gatsby`, | ||
{}, | ||
{ | ||
globalConfigPath: true, | ||
} | ||
) | ||
} | ||
|
||
return config | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import path from "path" | ||
|
||
module.exports = () => { | ||
try { | ||
return require(path.join( | ||
process.cwd(), | ||
`node_modules`, | ||
`gatsby`, | ||
`package.json` | ||
)).version | ||
} catch (e) { | ||
return `` | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { | ||
setFeedbackDisabledValue, | ||
showFeedbackRequest, | ||
} from "../utils/feedback" | ||
import { IProgram } from "./types" | ||
|
||
// This is because we splat command line arguments onto this object. | ||
// A good refactor would be to put this inside a key like `cliArgs` | ||
interface IFeedbackProgram extends IProgram { | ||
disable?: boolean | ||
enable?: boolean | ||
} | ||
|
||
module.exports = async function feedback( | ||
program: IFeedbackProgram | ||
): Promise<void> { | ||
if (program.disable) { | ||
program.report.info(`Disabling gatsby feedback requests`) | ||
setFeedbackDisabledValue(true) | ||
return | ||
} | ||
|
||
if (program.enable) { | ||
program.report.info(`Enabling gatsby feedback requests`) | ||
setFeedbackDisabledValue(false) | ||
return | ||
} | ||
|
||
showFeedbackRequest() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
import { getConfigStore, getGatsbyVersion } from "gatsby-core-utils" | ||
import { | ||
setFeedbackDisabledValue, | ||
userPassesFeedbackRequestHeuristic, | ||
} from "../feedback" | ||
jest.mock(`date-fns/getDayOfYear`, (): (() => number) => (): number => { | ||
// This is required for Hueristic 1 to always match up | ||
// When Math.random returns 1 (mocked in the `clearStateToAllowHeuristicsToPass` fn) | ||
const currentQuarter = Math.floor((new Date().getMonth() + 3) / 3) | ||
return 1 * 30 * 3 * currentQuarter | ||
}) | ||
jest.mock(`gatsby-core-utils`, () => { | ||
return { | ||
...jest.requireActual(`gatsby-core-utils`), | ||
getGatsbyVersion: jest.fn(() => `2.1.1`), | ||
} | ||
}) | ||
|
||
jest.mock(`latest-version`, (): (() => Promise<string>) => (): Promise< | ||
string | ||
> => Promise.resolve(`2.1.1`)) | ||
|
||
const dateFromSixMonthsAgo = new Date() | ||
dateFromSixMonthsAgo.setMonth(dateFromSixMonthsAgo.getMonth() - 6) | ||
const mathRandom = Math.random | ||
|
||
// This function resets all state to make the heuristic | ||
// checks all pass. This is to be used to make sure an individual | ||
// test truly only gets triggered by the state manipulations | ||
// that exist within that test. | ||
const clearStateToAllowHeuristicsToPass = (): void => { | ||
// Heuristic 1 | ||
Math.random = jest.fn(() => 1) | ||
// Heuristic 2 | ||
setFeedbackDisabledValue(false) | ||
// Heuristic 3 | ||
delete process.env.GATSBY_FEEDBACK_DISABLED | ||
// Heuristic 4 | ||
getConfigStore().set(`feedback.lastRequestDate`, dateFromSixMonthsAgo) | ||
// Heuristic 5 | ||
;(getGatsbyVersion as jest.Mock).mockReturnValue(`2.1.1`) | ||
} | ||
|
||
describe(`feedback`, () => { | ||
describe(`userPassesFeedbackRequestHeuristic returns false when`, () => { | ||
beforeEach(clearStateToAllowHeuristicsToPass) | ||
|
||
afterEach(() => { | ||
Math.random = mathRandom | ||
}) | ||
|
||
it(`Heuristic 1: The random number generator hits today`, async () => { | ||
// ensure default is passing before manipulating a test | ||
expect(await userPassesFeedbackRequestHeuristic()).toBe(true) | ||
|
||
// Change the random value to return a different date | ||
;(Math.random as jest.Mock).mockReturnValue(0.5) | ||
expect(await userPassesFeedbackRequestHeuristic()).toBe(false) | ||
|
||
// Unset to ensure tests are stable | ||
;(Math.random as jest.Mock).mockReturnValue(1) | ||
expect(await userPassesFeedbackRequestHeuristic()).toBe(true) | ||
}) | ||
|
||
it(`Heuristic 2: the gatsby disabled key is set to false`, async () => { | ||
// ensure default is passing before manipulating a test | ||
expect(await userPassesFeedbackRequestHeuristic()).toBe(true) | ||
|
||
setFeedbackDisabledValue(true) | ||
expect(await userPassesFeedbackRequestHeuristic()).toBe(false) | ||
|
||
// Unset to ensure tests are stable | ||
setFeedbackDisabledValue(false) | ||
expect(await userPassesFeedbackRequestHeuristic()).toBe(true) | ||
}) | ||
|
||
it("Heuristic 3: the process.env.GATSBY_FEEDBACK_DISABLED argument is set to `1`", async () => { | ||
// ensure default is passing before manipulating a test | ||
expect(await userPassesFeedbackRequestHeuristic()).toBe(true) | ||
|
||
process.env.GATSBY_FEEDBACK_DISABLED = `1` | ||
expect(await userPassesFeedbackRequestHeuristic()).toBe(false) | ||
|
||
// Unset to ensure tests are stable | ||
process.env.GATSBY_FEEDBACK_DISABLED = `0` | ||
expect(await userPassesFeedbackRequestHeuristic()).toBe(true) | ||
}) | ||
|
||
it(`Heuristic 4: It has been more than 3 months since the last feedback request`, async () => { | ||
// ensure default is passing before manipulating a test | ||
expect(await userPassesFeedbackRequestHeuristic()).toBe(true) | ||
|
||
// Set last prompt date to today | ||
getConfigStore().set(`feedback.lastRequestDate`, Date.now()) | ||
expect(await userPassesFeedbackRequestHeuristic()).toBe(false) | ||
|
||
// Unset to ensure tests are stable | ||
getConfigStore().set(`feedback.lastRequestDate`, dateFromSixMonthsAgo) | ||
expect(await userPassesFeedbackRequestHeuristic()).toBe(true) | ||
}) | ||
|
||
it(`Heuristic 5: The installed Gatsby is on the latest major + minor version`, async () => { | ||
// ensure default is passing before manipulating a test | ||
expect(await userPassesFeedbackRequestHeuristic()).toBe(true) | ||
|
||
// Mock the installed version to be a previous minor to force false | ||
;(getGatsbyVersion as jest.Mock).mockReturnValue(`2.0.0`) | ||
expect(await userPassesFeedbackRequestHeuristic()).toBe(false) | ||
|
||
// Unset to ensure tests are stable | ||
;(getGatsbyVersion as jest.Mock).mockReturnValue(`2.1.1`) | ||
expect(await userPassesFeedbackRequestHeuristic()).toBe(true) | ||
}) | ||
}) | ||
}) |
Oops, something went wrong.