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

MP query freshness checker prototype #4462

Merged
merged 28 commits into from
Feb 27, 2021
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# .circleci/config.yml

version: 2.1

orbs:
Expand Down Expand Up @@ -226,6 +224,33 @@ jobs:
name: Prevent Strictness Regressions
command: node scripts/strictness-migration.js check-pr

check-metaphysics-freshness:
docker:
- image: circleci/node:14.13.1
steps:
- checkout
- run:
name: apt-get update
command: sudo apt-get update --fix-missing
- run:
name: Install Headless Chrome dependencies for puppeteer
# from https://github.com/threetreeslight/puppeteer-orb/blob/master/orb.yml
command: |
sudo apt-get install --fix-missing -yq \
gconf-service libasound2 libatk1.0-0 libatk-bridge2.0-0 libc6 libcairo2 libcups2 libdbus-1-3 \
libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 \
libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 \
libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates \
fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget
- generate-checksums
- install-node-modules
- run:
name: Generate queries json
command: yarn relay
- run:
name: Check Metaphysics freshness
command: yarn ts-node ./metaphysics-queries-freshness-tests/test-freshness.ts

build-test-js:
executor:
name: node/default
Expand Down Expand Up @@ -412,6 +437,7 @@ workflows:

test-build-deploy:
jobs:
- check-metaphysics-freshness
- check-pr:
filters:
branches:
Expand Down
153 changes: 153 additions & 0 deletions metaphysics-queries-freshness-tests/test-freshness.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
#!/usr/bin/env yarn ts-node

require("dotenv").config()

import { GraphQLClient } from "graphql-request"
import { values } from "lodash"
import { exit, stdout } from "process"
import puppeteer from "puppeteer"

const login = async (): Promise<{ userId: string; accessToken: string }> => {
console.log("Logging in..")
const browser = await puppeteer.launch({ headless: true })
const page = await browser.newPage()
await page.goto("https://staging.artsy.net")
await page.click('aria/button[name="Log in"]')
await page.click('aria/textbox[name="Enter your email address"]')
await page.type('aria/textbox[name="Enter your email address"]', process.env.FRESHNESS_TEST_EMAIL ?? "missing email")
await page.click('aria/textbox[name="Enter your password"]')
await page.type('aria/textbox[name="Enter your password"]', process.env.FRESHNESS_TEST_PASSWORD ?? "missing password")
await page.click('aria/pushbutton[name="Log in"]')
await page.waitForNavigation()
const { id: userId, accessToken } = await page.evaluate("sd.CURRENT_USER")
console.log("Logged in.")
return { userId, accessToken }
}

const doIt = async (): Promise<never> => {
const { userId, accessToken } = await login()
const metaphysics = new GraphQLClient("https://metaphysics-staging.artsy.net/v2", {
headers: {
"X-Access-Token": accessToken,
"X-User-Id": userId,
},
})

const allQueries = values(require("../data/complete.queryMap.json")) as string[]
const problemQueries = allQueries.filter(
(q) =>
q.includes("$conversationID") ||
q.includes("ArtistRailNewSuggestionQuery") ||
q.includes("ArtistSeriesQuery") ||
q.includes("ArtworkMediumQuery") ||
q.includes("AuctionResultQuery") ||
q.includes("AutosuggestResultsQuery") ||
q.includes("BidFlowQuery") ||
q.includes("BidderPositionQuery") ||
q.includes("BottomTabsModelFetchCurrentUnreadConversationCountQuery") ||
q.includes("ConfirmBidRefetchQuery") ||
q.includes("ConsignmentsArtistQuery") ||
q.includes("ConversationQuery") ||
q.includes("FairArticlesQuery") ||
q.includes("FairExhibitorsQuery") ||
q.includes("FeatureQuery") ||
q.includes("GeneQuery") ||
q.includes("InboxOldQuery") ||
q.includes("MapRendererQuery") ||
q.includes("PartnerLocationsQuery") ||
q.includes("PartnerQuery") ||
q.includes("PartnerRefetchQuery") ||
q.includes("PriceSummaryQuery") ||
q.includes("RegistrationFlowQuery") ||
q.includes("SaleAboveTheFoldQuery") ||
q.includes("SaleActiveBidsRefetchQuery") ||
q.includes("SaleBelowTheFoldQuery") ||
q.includes("SaleInfoQueryRendererQuery") ||
q.includes("SaleRefetchQuery") ||
q.includes("SelectMaxBidRefetchQuery") ||
q.includes("ShowMoreInfoQuery") ||
q.includes("ShowQuery") ||
q.includes("VanityURLEntityQuery")
)
const allQueriesToCheck = allQueries.filter((q) => !problemQueries.includes(q))
const allNonTestQueries = allQueriesToCheck.filter(
(q) => !q.includes("Test") && !q.includes("Mock") && !q.includes("Fixtures")
)
const queries = allNonTestQueries.filter((q) => q.startsWith("query"))
const queriesWithoutVars = queries.filter((q) => !q.includes("$"))
const queriesWithCursor = queries.filter((q) => q.includes("$cursor"))
const queriesWithVars = queries.filter((q) => !queriesWithoutVars.includes(q) && !queriesWithCursor.includes(q))
const mutations = allNonTestQueries.filter((q) => q.startsWith("mutation"))

console.warn(`Skipping ${mutations.length} mutations`)
console.log(`Skipping ${allQueries.length - allNonTestQueries.length} test queries`)
console.warn(`Skipping ${queriesWithCursor.length} queries with cursors`)

type Error = { request: string; error: string }
const errors: Error[] = [] as Error[]
const executeRequests = async (
requests: string[],
description: string,
options: { verbose?: boolean; vars?: { [Var: string]: any } } = { verbose: false }
) => {
const log = (...args: Parameters<typeof console.log>) => {
if (options.verbose) {
console.log(...args)
}
}

console.log(`Running ${requests.length} ${description}`)
await Promise.all(
requests.map(async (req) => {
try {
log(req)
const response = await metaphysics.request(req, options.vars)
stdout.write(".")
log(JSON.stringify(response))
} catch (e) {
stdout.write("x")
errors.push({ request: req, error: e })
}
})
)
console.log("")
}

await executeRequests(queriesWithoutVars, "no-var queries")

await executeRequests(queriesWithVars, "var queries", {
vars: {
artworkID: "felipe-pantone-subtractive-variability-silk-robe-w-slash-j-balvin",
artworkSlug: "felipe-pantone-subtractive-variability-silk-robe-w-slash-j-balvin",
fairID: "london-art-fair-edit",
citySlug: "athens-greece",
artistInternalID: "4dd1584de0091e000100207c", // banksy
artistSlug: "banksy",
artistID: "banksy",
medium: "prints",
collectionID: "agnes-martin-lithographs",
viewingRoomID: "movart-mario-macilau-circle-of-memories",
isPad: false,
heroImageVersion: "NARROW",
count: 4,
},
})

// end game
if (errors.length !== 0) {
console.error(`Oh noes! ${errors.length} queries failed!`)
errors.map(({ request, error }) => {
console.warn("- The following query:")
console.log(request)
ds300 marked this conversation as resolved.
Show resolved Hide resolved
console.warn("failed with error:")
console.log(error)
})
console.error(`Again, ${errors.length} queries failed. Look above for more details.`)
exit(-1)
}
console.log("Success! Our queries are so so fresh.")
exit(0)
}

doIt()

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -181,10 +181,12 @@
"danger": "6.1.1",
"danger-plugin-jest": "1.1.0",
"dedent": "0.7.0",
"dotenv": "8.2.0",
"enzyme": "3.9.0",
"enzyme-adapter-react-16": "1.13.0",
"glob": "7.1.6",
"graphql": "14.5.6",
"graphql-request": "3.4.0",
"husky": "4.2.5",
"jest": "25.2.7",
"jest-fetch-mock": "^3.0.3",
Expand All @@ -202,6 +204,7 @@
"postinstall-prepare": "1.0.1",
"prettier": "^2.2.0",
"pull-lock": "1.0.0",
"puppeteer": "^7.1.0",
"react-dom": "16.8.3",
"react-relay-network-modern": "4.7.1",
"react-test-renderer": "16.13.1",
Expand Down
Loading