Skip to content

Commit

Permalink
checks and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
enisdenjo committed Oct 16, 2024
1 parent 196d400 commit 17b7226
Show file tree
Hide file tree
Showing 12 changed files with 906 additions and 54 deletions.
70 changes: 70 additions & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: Check

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
format:
name: Format
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up env
uses: the-guild-org/shared-config/setup@v1
with:
node-version-file: .node-version
- name: Install
run: yarn install
- name: Check
run: yarn check:format

lint:
name: Lint
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up env
uses: the-guild-org/shared-config/setup@v1
with:
node-version-file: .node-version
- name: Install
run: yarn install
- name: Check
run: yarn check:lint

types:
name: Types
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up env
uses: the-guild-org/shared-config/setup@v1
with:
node-version-file: .node-version
- name: Install
run: yarn install
- name: Check
run: yarn check:types

build: # making sure build works so it doesn't fail on us during release
name: Build
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up env
uses: the-guild-org/shared-config/setup@v1
with:
node-version-file: .node-version
- name: Install
run: yarn install
- name: Check
run: yarn build
47 changes: 0 additions & 47 deletions .github/workflows/ci.yml

This file was deleted.

32 changes: 32 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Test

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
unit:
strategy:
fail-fast: false
matrix:
node-version:
- 18
- 20
- 22
name: Unit / Node v${{matrix.node-version}}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up env
uses: the-guild-org/shared-config/setup@v1
with:
node-version: ${{matrix.node-version}}
- name: Install
run: yarn install
- name: Test
run: yarn test
1 change: 1 addition & 0 deletions .prettierrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ importOrderParserPlugins:
- typescript
- jsx
- decorators-legacy
- explicitResourceManagement
8 changes: 8 additions & 0 deletions internal/testing/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "@internal/testing",
"private": true,
"devDependencies": {
"@types/node": "^22.7.5",
"@whatwg-node/disposablestack": "^0.0.5"
}
}
50 changes: 50 additions & 0 deletions internal/testing/src/createDisposableServer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { createServer } from 'node:http';
import type { RequestListener, Server } from 'node:http';
import type { AddressInfo, Socket } from 'node:net';
import { DisposableSymbols } from '@whatwg-node/disposablestack';

export interface DisposableServerOpts {
port?: number;
}

export interface DisposableServer {
address(): AddressInfo;
[DisposableSymbols.asyncDispose](): Promise<void>;
server: Server;
}

export async function createDisposableServer(
requestListener?: RequestListener,
opts?: DisposableServerOpts,
): Promise<DisposableServer> {
const server = createServer(requestListener);
const port = opts?.port || 0;
await new Promise<void>((resolve, reject) => {
server.once('error', (err) => reject(err));
server.listen(port, () => resolve());
});
const sockets = new Set<Socket>();
server.on('connection', (socket) => {
sockets.add(socket);
socket.once('close', () => {
sockets.delete(socket);
});
});
return {
address() {
return server.address() as AddressInfo;
},
[DisposableSymbols.asyncDispose]() {
for (const socket of sockets) {
socket.destroy();
}
server.closeAllConnections();
return new Promise<void>((resolve, reject) => {
server.close((err) => (err ? reject(err) : resolve()));
});
},
get server(): Server {
return server;
},
};
}
1 change: 1 addition & 0 deletions internal/testing/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './createDisposableServer';
11 changes: 8 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@
"type": "module",
"private": true,
"workspaces": [
"packages/*"
"packages/*",
"internal/*"
],
"packageManager": "[email protected]",
"scripts": {
"build": "yarn workspaces foreach -A -p run build",
"check:format": "prettier --check .",
"check:lint": "eslint 'packages/**/src/**/*.ts'",
"check:type": "yarn tsc",
"format": "yarn check:format --write"
"format": "yarn check:format --write",
"test": "vitest"
},
"devDependencies": {
"@ianvs/prettier-plugin-sort-imports": "^4.3.1",
Expand All @@ -24,7 +26,10 @@
"prettier-plugin-pkg": "^0.18.1",
"prettier-plugin-sh": "^0.14.0",
"typescript": "^5.6.3",
"typescript-eslint": "^8.9.0"
"typescript-eslint": "^8.9.0",
"vite": "^5.4.9",
"vite-tsconfig-paths": "^5.0.1",
"vitest": "^2.1.3"
},
"resolutions": {
"graphql": "^16.9.0"
Expand Down
75 changes: 75 additions & 0 deletions packages/runtime/tests/upstreamCancellation.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { createDisposableServer } from '@internal/testing';
import { fetch } from '@whatwg-node/fetch';
import { createServerAdapter, Response } from '@whatwg-node/server';
import { createSchema, createYoga } from 'graphql-yoga';
import { describe, expect, it, vitest } from 'vitest';
import { createGatewayRuntime } from '../src/createGatewayRuntime';

describe('Upstream Cancellation', () => {
it('cancels upstream requests when the client cancels', async () => {
const serveRuntimeFetchCallAbortCtrl = new AbortController();
let resolveDataSource: (response: Response) => void;
const abortSpyOnDataSource = vitest.fn(() => {
resolveDataSource(new Response('Bye!'));
});
const dataSourceFetchSpy = vitest.fn((res: Response) => res.text());
const dataSourceAdapter = createServerAdapter((req) => {
serveRuntimeFetchCallAbortCtrl.abort();
req.signal.addEventListener('abort', abortSpyOnDataSource);
return new Promise((resolve) => {
resolveDataSource = resolve;
});
});
await using dataSourceServer =
await createDisposableServer(dataSourceAdapter);
const upstreamGraphQL = createYoga({
logging: false,
schema: createSchema({
typeDefs: /* GraphQL */ `
type Query {
hello: String
}
`,
resolvers: {
Query: {
hello: (_root, _args, context) =>
fetch(`http://localhost:${dataSourceServer.address().port}`, {
signal: context.request.signal,
}).then(dataSourceFetchSpy),
},
},
}),
});
await using upstreamGraphQLServer =
await createDisposableServer(upstreamGraphQL);
await using serveRuntime = createGatewayRuntime({
proxy: {
endpoint: `http://localhost:${upstreamGraphQLServer.address().port}/graphql`,
},
upstreamCancellation: true,
logging: false,
});
await using serveRuntimeServer = await createDisposableServer(serveRuntime);
const res$ = fetch(
`http://localhost:${serveRuntimeServer.address().port}/graphql`,
{
method: 'POST',
headers: {
'content-type': 'application/json',
},
body: JSON.stringify({
query: /* GraphQL */ `
query {
hello
}
`,
}),
signal: serveRuntimeFetchCallAbortCtrl.signal,
},
);
await expect(res$).rejects.toThrow();
expect(dataSourceFetchSpy).not.toHaveBeenCalled();
await new Promise<void>((resolve) => setTimeout(resolve, 300));
expect(abortSpyOnDataSource).toHaveBeenCalled();
});
});
9 changes: 8 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,15 @@
"target": "esnext",
// packages
"paths": {
"@internal/testing": ["./internal/testing/src/index.ts"],
"@graphql-hive/gateway-runtime": ["./packages/runtime/src/index.ts"]
}
},
"include": ["eslint.config.js", "packages/**/src", "packages/**/scripts"]
"include": [
"./eslint.config.js",
"./internal/**/src",
"./packages/**/src",
"./packages/**/tests",
"./packages/**/scripts"
]
}
6 changes: 6 additions & 0 deletions vitest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import tsconfigPaths from 'vite-tsconfig-paths';
import { defineConfig } from 'vitest/config';

export default defineConfig({
plugins: [tsconfigPaths()],
});
Loading

0 comments on commit 17b7226

Please sign in to comment.