: 'babel-jest',\n '^.+\\\\.ts?
: 'babel-jest',\n '^.+\\\\.js
: 'babel-jest',\n },\n};\n","id":"mod_KMReKNkGAiEEDnYx4K187W","is_binary":false,"title":"jest.config.js","sha":null,"inserted_at":"2025-12-14T02:10:09","updated_at":"2025-12-14T02:10:09","upload_id":null,"shortid":"5EptEVeL2U","source_id":"src_PKQW4PzXEEMfyQQXrqy8uU","directory_shortid":null},{"code":"{\n \"name\": \"continuous-integration-testing\",\n \"version\": \"0.0.0\",\n \"license\": \"MIT\",\n \"main\": \"index.js\",\n \"scripts\": {\n \"start\": \"ts-node-dev src\u002Findex.ts\",\n \"test\": \"jest test\"\n },\n \"dependencies\": {\n \"@graphql-tools\u002Fdelegate\": \"^12.0.0\",\n \"@graphql-tools\u002Fexecutor-http\": \"^3.0.2\",\n \"@graphql-tools\u002Fstitch\": \"^10.0.1\",\n \"@graphql-tools\u002Fstitching-directives\": \"^4.0.1\",\n \"graphql\": \"^16.6.0\",\n \"graphql-yoga\": \"^5.16.2\"\n },\n \"devDependencies\": {\n \"@babel\u002Fcore\": \"7.28.5\",\n \"@babel\u002Fplugin-proposal-class-properties\": \"7.18.6\",\n \"@babel\u002Fpreset-env\": \"7.28.5\",\n \"@babel\u002Fpreset-typescript\": \"7.28.5\",\n \"@graphql-tools\u002Fmock\": \"^9.0.0\",\n \"@graphql-tools\u002Futils\": \"^10.0.0\",\n \"@types\u002Fjest\": \"^30.0.0\",\n \"@types\u002Fnode\": \"^25.0.1\",\n \"jest\": \"^30.0.0\",\n \"typescript\": \"5.9.3\"\n }\n}\n","id":"mod_15UJGorPWoiMoGPBSHRXJ5","is_binary":false,"title":"package.json","sha":null,"inserted_at":"2025-12-14T02:10:09","updated_at":"2025-12-14T02:10:09","upload_id":null,"shortid":"yIup9m0n1V","source_id":"src_PKQW4PzXEEMfyQQXrqy8uU","directory_shortid":null},{"code":"{\n \"services\": {\n \"products\": {\n \"url\": \"http:\u002F\u002Flocalhost:4001\u002Fgraphql\"\n },\n \"reviews\": {\n \"url\": \"http:\u002F\u002Flocalhost:4002\u002Fgraphql\"\n },\n \"users\": {\n \"url\": \"http:\u002F\u002Flocalhost:4003\u002Fgraphql\"\n }\n }\n}\n","id":"mod_13LURwgQWuNyYF5aFf2rKJ","is_binary":false,"title":"config.json","sha":null,"inserted_at":"2025-12-14T02:10:09","updated_at":"2025-12-14T02:10:09","upload_id":null,"shortid":"hpvtRW4lfh","source_id":"src_PKQW4PzXEEMfyQQXrqy8uU","directory_shortid":"A2HYX9jpF"},{"code":"import { createServer } from 'node:http';\nimport { createYoga } from 'graphql-yoga';\nimport { buildGatewaySchema, buildSubschemaConfigs } from '.\u002Fschema_builder';\n\nconst schema = buildGatewaySchema(buildSubschemaConfigs());\n\nconst server = createServer(createYoga({ schema }));\n\nserver.listen(4000, () =\u003E console.log('gateway running at http:\u002F\u002Flocalhost:4000\u002Fgraphql'));\n","id":"mod_ESsbVPTtLpYBPP1RnTioXR","is_binary":false,"title":"index.ts","sha":null,"inserted_at":"2025-12-14T02:10:09","updated_at":"2025-12-14T02:10:09","upload_id":null,"shortid":"Dcb24IULJ5","source_id":"src_PKQW4PzXEEMfyQQXrqy8uU","directory_shortid":"A2HYX9jpF"},{"code":"directive @key(selectionSet: String!) on OBJECT\ndirective @merge(\n keyField: String\n keyArg: String\n additionalArgs: String\n key: [String!]\n argsExpr: String\n) on FIELD_DEFINITION\ndirective @computed(selectionSet: String!) on FIELD_DEFINITION\n\ntype Product {\n upc: ID!\n name: String!\n price: Int!\n weight: Int!\n}\n\ntype Query {\n products(upcs: [ID!]!): [Product]! @merge(keyField: \"upc\")\n _sdl: String!\n}\n","id":"mod_K9Py6yD7MpbKRD4oGiEJ32","is_binary":false,"title":"products.graphql","sha":null,"inserted_at":"2025-12-14T02:10:09","updated_at":"2025-12-14T02:10:09","upload_id":null,"shortid":"L2frMRhfjS","source_id":"src_PKQW4PzXEEMfyQQXrqy8uU","directory_shortid":"0OSRHGUyN2"},{"code":"directive @key(selectionSet: String!) on OBJECT\ndirective @merge(\n keyField: String\n keyArg: String\n additionalArgs: String\n key: [String!]\n argsExpr: String\n) on FIELD_DEFINITION\ndirective @computed(selectionSet: String!) on FIELD_DEFINITION\n\ntype Review {\n id: ID!\n body: String\n author: User\n product: Product\n}\n\ntype User {\n id: ID!\n totalReviews: Int!\n reviews: [Review]\n}\n\ntype Product {\n upc: ID!\n reviews: [Review]\n}\n\ntype Query {\n review(id: ID!): Review\n _users(ids: [ID!]!): [User]! @merge(keyField: \"id\")\n _products(upcs: [ID!]!): [Product]! @merge(keyField: \"upc\")\n _sdl: String!\n}\n","id":"mod_DQjG9fnz2c7uETUzGezC9R","is_binary":false,"title":"reviews.graphql","sha":null,"inserted_at":"2025-12-14T02:10:09","updated_at":"2025-12-14T02:10:09","upload_id":null,"shortid":"fmQryy5LoC","source_id":"src_PKQW4PzXEEMfyQQXrqy8uU","directory_shortid":"0OSRHGUyN2"},{"code":"directive @key(selectionSet: String!) on OBJECT\ndirective @merge(\n keyField: String\n keyArg: String\n additionalArgs: String\n key: [String!]\n argsExpr: String\n) on FIELD_DEFINITION\ndirective @computed(selectionSet: String!) on FIELD_DEFINITION\n\ntype User {\n id: ID!\n name: String!\n username: String!\n}\n\ntype Query {\n user(id: ID!): User @merge(keyField: \"id\")\n _sdl: String!\n}\n","id":"mod_HDLGni9pNyrSSYbwMqMmPL","is_binary":false,"title":"users.graphql","sha":null,"inserted_at":"2025-12-14T02:10:09","updated_at":"2025-12-14T02:10:09","upload_id":null,"shortid":"y8xe2Ur5up","source_id":"src_PKQW4PzXEEMfyQQXrqy8uU","directory_shortid":"0OSRHGUyN2"},{"code":"import { readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { buildSchema } from 'graphql';\nimport { SubschemaConfig } from '@graphql-tools\u002Fdelegate';\nimport { buildHTTPExecutor } from '@graphql-tools\u002Fexecutor-http';\nimport { stitchSchemas } from '@graphql-tools\u002Fstitch';\nimport { stitchingDirectives } from '@graphql-tools\u002Fstitching-directives';\nimport config from '.\u002Fconfig.json';\n\nexport function buildSubschemaConfigs(): Record\u003Cstring, SubschemaConfig\u003E {\n return Object.entries(config.services).reduce((memo, [name, settings]) =\u003E {\n const sdl = readFileSync(join(__dirname, `.\u002Fremote_schemas\u002F${name}.graphql`), 'utf-8');\n memo[name] = {\n schema: buildSchema(sdl),\n executor: buildHTTPExecutor({ endpoint: settings.url }),\n batch: true,\n };\n return memo;\n }, {});\n}\n\nexport function buildGatewaySchema(subschemasByName: Record\u003Cstring, SubschemaConfig\u003E) {\n const { stitchingDirectivesTransformer } = stitchingDirectives();\n\n return stitchSchemas({\n subschemaConfigTransforms: [stitchingDirectivesTransformer],\n subschemas: Object.values(subschemasByName),\n });\n}\n","id":"mod_PRps9gM3yRFfsk1KNjCmMe","is_binary":false,"title":"schema_builder.ts","sha":null,"inserted_at":"2025-12-14T02:10:09","updated_at":"2025-12-14T02:10:09","upload_id":null,"shortid":"G1RsYrDZIX","source_id":"src_PKQW4PzXEEMfyQQXrqy8uU","directory_shortid":"A2HYX9jpF"},{"code":"import { queryMockedGateway } from '.\u002Ftest_helper';\n\ndescribe('gateway schema', () =\u003E {\n const USER_QUERY = \u002F* GraphQL *\u002F `\n {\n user(id: \"1\") {\n # id \u003C\u003C must work without this selected\n name\n username\n reviews {\n # id \u003C\u003C must work without this selected\n body\n product {\n # upc \u003C\u003C must work without this selected\n name\n price\n weight\n }\n }\n }\n }\n `;\n\n test('resolves users -\u003E reviews -\u003E products', async () =\u003E {\n const { data } = await queryMockedGateway(USER_QUERY);\n\n expect(data).toEqual({\n user: {\n name: 'users-value',\n username: 'hansolo',\n reviews: [\n {\n body: 'great',\n product: {\n name: 'gizmo',\n price: 23,\n weight: 23,\n },\n },\n ],\n },\n });\n });\n\n const REVIEW_QUERY = \u002F* GraphQL *\u002F `\n {\n review(id: \"1\") {\n # id \u003C\u003C must work without this selected\n body\n author {\n # id \u003C\u003C must work without this selected\n name\n username\n }\n product {\n # upc \u003C\u003C must work without this selected\n name\n price\n weight\n }\n }\n }\n `;\n\n test('resolves review -\u003E author + product', async () =\u003E {\n const { data } = await queryMockedGateway(REVIEW_QUERY);\n\n expect(data).toEqual({\n review: {\n body: 'great',\n author: {\n name: 'users-value',\n username: 'hansolo',\n },\n product: {\n name: 'gizmo',\n price: 23,\n weight: 23,\n },\n },\n });\n });\n\n const PRODUCTS_QUERY = \u002F* GraphQL *\u002F `\n {\n products(upcs: [\"2\"]) {\n # upc \u003C\u003C must work without this selected\n name\n price\n weight\n reviews {\n # id \u003C\u003C must work without this selected\n body\n author {\n # id \u003C\u003C must work without this selected\n name\n username\n }\n }\n }\n }\n `;\n\n test('resolves products -\u003E reviews -\u003E user', async () =\u003E {\n const { data } = await queryMockedGateway(PRODUCTS_QUERY);\n\n expect(data).toEqual({\n products: [\n {\n name: 'widget',\n price: 23,\n weight: 23,\n reviews: [\n {\n body: 'awful',\n author: {\n name: 'users-value',\n username: 'yoda',\n },\n },\n ],\n },\n ],\n });\n });\n});\n","id":"mod_QoTTQvSXbriMJr8gDfdRbM","is_binary":false,"title":"gateway.test.ts","sha":null,"inserted_at":"2025-12-14T02:10:09","updated_at":"2025-12-14T02:10:09","upload_id":null,"shortid":"Gr0HuF8MgE","source_id":"src_PKQW4PzXEEMfyQQXrqy8uU","directory_shortid":"32pG47-Anh"},{"code":"const products = [\n { upc: '1', name: 'gizmo' },\n { upc: '2', name: 'widget' },\n];\n\nexport const resolvers = {\n Query: {\n products: (_, { upcs }) =\u003E upcs.map(upc =\u003E products.find(p =\u003E p.upc === upc)),\n },\n};\n\nexport const mocks = {\n Int: () =\u003E 23,\n};\n","id":"mod_RpxgU62ZneWj6i85xgE5Gw","is_binary":false,"title":"products.ts","sha":null,"inserted_at":"2025-12-14T02:10:09","updated_at":"2025-12-14T02:10:09","upload_id":null,"shortid":"eeiMg6DnRu","source_id":"src_PKQW4PzXEEMfyQQXrqy8uU","directory_shortid":"8CgZ5Bw565"},{"code":"import { IResolvers } from '@graphql-tools\u002Futils';\n\nconst reviews = [\n { id: '1', body: 'great', author: { id: '1' }, product: { upc: '1' } },\n { id: '2', body: 'awful', author: { id: '2' }, product: { upc: '2' } },\n];\n\nexport const resolvers: IResolvers = {\n Query: {\n review: (_, { id }) =\u003E reviews.find(r =\u003E r.id === id),\n _users: (_, { ids }) =\u003E ids.map((id: string) =\u003E ({ id })),\n _products: (_, { upcs }) =\u003E upcs.map((upc: string) =\u003E ({ upc })),\n },\n Product: {\n reviews: p =\u003E reviews.filter(r =\u003E r.product.upc === p.upc),\n },\n User: {\n reviews: u =\u003E reviews.filter(r =\u003E r.author.id === u.id),\n },\n};\n","id":"mod_B6Tx42jXg9DUT7B19hqnhy","is_binary":false,"title":"reviews.ts","sha":null,"inserted_at":"2025-12-14T02:10:09","updated_at":"2025-12-14T02:10:09","upload_id":null,"shortid":"R3rebB2I-tW","source_id":"src_PKQW4PzXEEMfyQQXrqy8uU","directory_shortid":"8CgZ5Bw565"},{"code":"const users = [\n { id: '1', username: 'hansolo' },\n { id: '2', username: 'yoda' },\n];\n\nexport const resolvers = {\n Query: {\n user: (_, { id }) =\u003E users.find(u =\u003E u.id === id),\n },\n};\n","id":"mod_R29hCEnyBMuDSqKLodrFdP","is_binary":false,"title":"users.ts","sha":null,"inserted_at":"2025-12-14T02:10:09","updated_at":"2025-12-14T02:10:09","upload_id":null,"shortid":"dGWVtUP5Fzb","source_id":"src_PKQW4PzXEEMfyQQXrqy8uU","directory_shortid":"8CgZ5Bw565"},{"code":"import { graphql } from 'graphql';\nimport { createSchema } from 'graphql-yoga';\nimport { addMocksToSchema, IMocks } from '@graphql-tools\u002Fmock';\nimport { stitchingDirectives } from '@graphql-tools\u002Fstitching-directives';\nimport { IResolvers, printSchemaWithDirectives } from '@graphql-tools\u002Futils';\nimport { buildGatewaySchema, buildSubschemaConfigs } from '..\u002Fsrc\u002Fschema_builder';\nimport * as productsFixtures from '.\u002Fmock_services\u002Fproducts';\nimport * as reviewsFixtures from '.\u002Fmock_services\u002Freviews';\nimport * as usersFixtures from '.\u002Fmock_services\u002Fusers';\n\n\u002F\u002F Setup a mapping of test fixtures by service name\n\ninterface Fixture {\n resolvers?: IResolvers;\n mocks?: IMocks;\n}\n\nconst fixturesByName: Record\u003Cstring, Fixture\u003E = {\n products: productsFixtures,\n reviews: reviewsFixtures,\n users: usersFixtures,\n};\n\n\u002F\u002F Get the actual subschemas built for the production app:\nconst subschemaConfigs = buildSubschemaConfigs();\n\n\u002F\u002F Reconfigure the subschema configurations for testing...\n\u002F\u002F makes all subschemas locally-executable,\n\u002F\u002F and sets them up with mocked fixture data to test with.\nObject.entries(subschemaConfigs).forEach(([name, subschemaConfig]) =\u003E {\n const fixtures = fixturesByName[name] || {};\n\n const { stitchingDirectivesValidator } = stitchingDirectives();\n\n \u002F\u002F build all of the base schemas into locally-executable test schemas\n \u002F\u002F apply mock service resolvers to give them some simple record fixtures\n const schema = stitchingDirectivesValidator(\n createSchema({\n typeDefs: printSchemaWithDirectives(subschemaConfig.schema),\n resolvers: fixtures.resolvers,\n }),\n );\n\n \u002F\u002F apply mocks to fill in missing values\n \u002F\u002F anything without a resolver or fixture data\n \u002F\u002F gets filled in with a predictable service-specific scalar\n subschemaConfig.schema = addMocksToSchema({\n preserveResolvers: true,\n schema,\n mocks: {\n String: () =\u003E `${name}-value`,\n ...(fixtures.mocks || {}),\n },\n });\n\n \u002F\u002F remove all executors (run everything as a locally-executable schema)\n delete subschemaConfig.executor;\n});\n\n\u002F\u002F Run the gateway builder using the mocked subservices\n\u002F\u002F this gives the complete stitched gateway talking to mocked services.\nconst mockedGateway = buildGatewaySchema(subschemaConfigs);\n\nexport function queryMockedGateway(query: string, variables: any = {}) {\n return graphql({\n schema: mockedGateway,\n source: query,\n variableValues: variables,\n });\n}\n","id":"mod_6cfyzfRdhbgjrakzo1Uayr","is_binary":false,"title":"test_helper.ts","sha":null,"inserted_at":"2025-12-14T02:10:09","updated_at":"2025-12-14T02:10:09","upload_id":null,"shortid":"uL4zEaM-yh1","source_id":"src_PKQW4PzXEEMfyQQXrqy8uU","directory_shortid":"32pG47-Anh"},{"code":"{\n \"compilerOptions\": {\n \"target\": \"esnext\",\n \"moduleResolution\": \"node\",\n \"module\": \"commonjs\",\n \"sourceMap\": true,\n \"allowSyntheticDefaultImports\": true,\n \"esModuleInterop\": true,\n \"lib\": [\"esnext\", \"DOM\"],\n \"skipLibCheck\": true,\n \"resolveJsonModule\": true\n }\n}\n","id":"mod_3hPiXYQzcAjMS9k46jY9sy","is_binary":false,"title":"tsconfig.json","sha":null,"inserted_at":"2025-12-14T02:10:09","updated_at":"2025-12-14T02:10:09","upload_id":null,"shortid":"LuJr4Ih9hMG","source_id":"src_PKQW4PzXEEMfyQQXrqy8uU","directory_shortid":null}],"fork_count":0,"settings":{"ai_consent":null,"use_pint":false},"is_sse":false,"template":"create-react-app","npm_registries":[],"draft":true,"view_count":7679,"version":123,"title":"continuous-integration-testing","privacy":0,"is_frozen":false,"id":"sbo9sj","v2":false,"preview_secret":null,"custom_template":{"id":"sbtempl_D45pYLPJQJG3bZ3KU7hRss","title":"continuous-integration-testing","v2":false,"color":"#61DAFB","url":null,"published":false,"sdk":false,"icon_url":"github","official":false},"sdk":false,"updated_at":"2025-12-14T02:10:09","pr_number":null,"npm_dependencies":{}};