Last active
February 15, 2022 22:06
-
-
Save smmoosavi/521077d41dc92023a2d4f423d266ea48 to your computer and use it in GitHub Desktop.
GraphQL schema to select html elements
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
var { graphql, GraphQLSchema, GraphQLString, GraphQLObjectType, GraphQLNonNull, GraphQLList } = require('graphql'); | |
// root query | |
const RootQuery = new GraphQLObjectType({ | |
name: 'RootQuery', | |
fields: () => QueryFields, | |
}); | |
const QueryFields = {}; | |
// element type | |
const GqlElement = new GraphQLObjectType({ | |
name: 'ELement', | |
fields: () => ELementFields, | |
}); | |
const ELementFields = {}; | |
// element query | |
QueryFields.root = { | |
type: GqlElement, | |
resolve: ({ rootElement }) => { | |
return { el: rootElement } | |
} | |
} | |
// select / select all / text / attr | |
ELementFields.select = { | |
type: GqlElement, | |
args: { | |
selector: { type: new GraphQLNonNull(GraphQLString) }, | |
}, | |
resolve: async ({ el }, { selector }, context, info) => { | |
const next = await context.driver.select(el, selector); | |
if (!next) { | |
return null; | |
} | |
return { el: next } | |
} | |
} | |
ELementFields.selectAll = { | |
type: new GraphQLNonNull(new GraphQLList(new GraphQLNonNull(GqlElement))), | |
args: { | |
selector: { type: new GraphQLNonNull(GraphQLString) }, | |
}, | |
resolve: async ({ el }, { selector }, context, info) => { | |
const next = await context.driver.selectAll(el, selector); | |
if (!next) { | |
return null | |
} | |
return next.map((el) => ({ el })) | |
} | |
} | |
ELementFields.text = { | |
type: GraphQLString, | |
resolve: async ({ el }, args, context, info) => { | |
const text = await context.driver.text(el); | |
return text | |
} | |
} | |
ELementFields.prop = { | |
type: GraphQLString, | |
args: { | |
name: { type: new GraphQLNonNull(GraphQLString) }, | |
}, | |
resolve: async ({ el }, { name }, context, info) => { | |
const value = await context.driver.prop(el, name); | |
return value | |
} | |
} | |
ELementFields.attr = { | |
type: GraphQLString, | |
args: { | |
name: { type: new GraphQLNonNull(GraphQLString) }, | |
}, | |
resolve: async ({ el }, { name }, context, info) => { | |
const value = await context.driver.attr(el, name); | |
return value | |
} | |
} | |
const schema = new GraphQLSchema({ query: RootQuery }); | |
const puppeteerContext = { | |
driver: { | |
select: async (el, selector) => el.$(selector), | |
selectAll: async (el, selector) => el.$$(selector), | |
text: async (el) => el.evaluate(e => e.innerText), | |
prop: async (el, propName) => el.evaluate((e, name) => e[name], propName), | |
attr: async (el, attrName) => el.evaluate((e, name) => e.getAttribute(name), attrName), | |
} | |
} | |
function exec(source, variableValues, rootElement) { | |
return graphql({ source, schema, variableValues, rootValue: { rootElement }, contextValue: puppeteerContext }); | |
} | |
module.exports = { exec }; |
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
query { | |
root { | |
title: select(selector: "#title") { text } | |
price: select(selector: "#price") { text value: attr(name: "data-value")} | |
sections: selectAll(selector: "#specs section") { | |
header: select(selector: ".section-header") { text } | |
rows: selectAll(selector: ".attribute-row") { | |
label: select(selector: ".attribute-label") { text } | |
value: select(selector: ".attribute-value") { text } | |
link: select(selector: "a") { href: prop(name: "href") } | |
} | |
} | |
} | |
} |
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
const page = await browser.newPage(); | |
await page.goto(url); | |
await exec(query, {}, page) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment