because I got bored of customising my CV for every job
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

test(server): add E2E tests and update seed scripts

+742 -3
+2 -2
apps/server/src/scripts/seed-test.ts
··· 1 1 import { NestFactory } from "@nestjs/core"; 2 - import { SeedModule } from "@/modules/seed/seed.module"; 3 - import { SeedService } from "@/modules/seed/seed.service"; 2 + import { SeedModule } from "@/modules/database/seed/seed.module"; 3 + import { SeedService } from "@/modules/database/seed/seed.service"; 4 4 5 5 async function main(): Promise<void> { 6 6 const app = await NestFactory.createApplicationContext(SeedModule);
+17
apps/server/src/scripts/seed.ts
··· 1 + import { NestFactory } from "@nestjs/core"; 2 + import { AppModule } from "../modules/app.module"; 3 + import { SeedService } from "../modules/database/seed/seed.service"; 4 + 5 + async function bootstrap() { 6 + const app = await NestFactory.createApplicationContext(AppModule); 7 + 8 + const seedService = app.get(SeedService); 9 + await seedService.seed(); 10 + 11 + await app.close(); 12 + process.exit(0); 13 + } 14 + 15 + bootstrap().catch((error) => { 16 + process.exit(1); 17 + });
+296
apps/server/test/auth-refresh-token.e2e-spec.ts
··· 1 + import { type INestApplication } from "@nestjs/common"; 2 + import { Test } from "@nestjs/testing"; 3 + import request from "supertest"; 4 + import { AppModule } from "@/modules/app.module"; 5 + 6 + describe("Auth - Refresh Token Flow (e2e)", () => { 7 + let app: INestApplication; 8 + let accessToken: string; 9 + let refreshToken: string; 10 + let expiresAt: string; 11 + 12 + beforeAll(async () => { 13 + const moduleRef = await Test.createTestingModule({ 14 + imports: [AppModule], 15 + }).compile(); 16 + 17 + app = moduleRef.createNestApplication(); 18 + await app.init(); 19 + }); 20 + 21 + afterAll(async () => { 22 + await app.close(); 23 + }); 24 + 25 + describe("Registration with refresh token", () => { 26 + it("should register a new user and return access token, refresh token, and expiry", async () => { 27 + const registerMutation = ` 28 + mutation Register($name: String!, $email: String!, $password: String!) { 29 + register(name: $name, email: $email, password: $password) { 30 + access_token 31 + refresh_token 32 + expires_at 33 + user { 34 + id 35 + email 36 + name 37 + } 38 + } 39 + } 40 + `; 41 + 42 + const response = await request(app.getHttpServer()) 43 + .post("/graphql") 44 + .send({ 45 + query: registerMutation, 46 + variables: { 47 + name: "Test User", 48 + email: `test-${Date.now()}@example.com`, 49 + password: "password123", 50 + }, 51 + }) 52 + .expect(200); 53 + 54 + expect(response.body.errors).toBeUndefined(); 55 + expect(response.body.data.register).toBeDefined(); 56 + expect(response.body.data.register.access_token).toBeDefined(); 57 + expect(response.body.data.register.refresh_token).toBeDefined(); 58 + expect(response.body.data.register.expires_at).toBeDefined(); 59 + expect(response.body.data.register.user).toBeDefined(); 60 + 61 + // Store tokens for later tests 62 + accessToken = response.body.data.register.access_token; 63 + refreshToken = response.body.data.register.refresh_token; 64 + expiresAt = response.body.data.register.expires_at; 65 + 66 + // Validate expiry is in the future 67 + const expiryDate = new Date(expiresAt); 68 + expect(expiryDate.getTime()).toBeGreaterThan(Date.now()); 69 + }); 70 + }); 71 + 72 + describe("Login with refresh token", () => { 73 + const testEmail = `login-test-${Date.now()}@example.com`; 74 + const testPassword = "password123"; 75 + 76 + beforeAll(async () => { 77 + // Register a user first 78 + const registerMutation = ` 79 + mutation Register($name: String!, $email: String!, $password: String!) { 80 + register(name: $name, email: $email, password: $password) { 81 + access_token 82 + } 83 + } 84 + `; 85 + 86 + await request(app.getHttpServer()) 87 + .post("/graphql") 88 + .send({ 89 + query: registerMutation, 90 + variables: { 91 + name: "Login Test User", 92 + email: testEmail, 93 + password: testPassword, 94 + }, 95 + }); 96 + }); 97 + 98 + it("should login and return access token, refresh token, and expiry", async () => { 99 + const loginMutation = ` 100 + mutation Login($email: String!, $password: String!) { 101 + login(email: $email, password: $password) { 102 + access_token 103 + refresh_token 104 + expires_at 105 + user { 106 + id 107 + email 108 + name 109 + } 110 + } 111 + } 112 + `; 113 + 114 + const response = await request(app.getHttpServer()) 115 + .post("/graphql") 116 + .send({ 117 + query: loginMutation, 118 + variables: { 119 + email: testEmail, 120 + password: testPassword, 121 + }, 122 + }) 123 + .expect(200); 124 + 125 + expect(response.body.errors).toBeUndefined(); 126 + expect(response.body.data.login).toBeDefined(); 127 + expect(response.body.data.login.access_token).toBeDefined(); 128 + expect(response.body.data.login.refresh_token).toBeDefined(); 129 + expect(response.body.data.login.expires_at).toBeDefined(); 130 + expect(response.body.data.login.user.email).toBe(testEmail); 131 + }); 132 + }); 133 + 134 + describe("Refresh Token Mutation", () => { 135 + it("should refresh access token using refresh token", async () => { 136 + const refreshMutation = ` 137 + mutation RefreshToken($refresh_token: String!) { 138 + refreshToken(refresh_token: $refresh_token) { 139 + access_token 140 + refresh_token 141 + expires_at 142 + } 143 + } 144 + `; 145 + 146 + const response = await request(app.getHttpServer()) 147 + .post("/graphql") 148 + .send({ 149 + query: refreshMutation, 150 + variables: { 151 + refresh_token: refreshToken, 152 + }, 153 + }) 154 + .expect(200); 155 + 156 + expect(response.body.errors).toBeUndefined(); 157 + expect(response.body.data.refreshToken).toBeDefined(); 158 + expect(response.body.data.refreshToken.access_token).toBeDefined(); 159 + expect(response.body.data.refreshToken.refresh_token).toBeDefined(); 160 + expect(response.body.data.refreshToken.expires_at).toBeDefined(); 161 + 162 + // New tokens should be different from old ones (JWT includes iat timestamp) 163 + expect(response.body.data.refreshToken.access_token).toBeDefined(); 164 + expect(response.body.data.refreshToken.refresh_token).toBeDefined(); 165 + expect(typeof response.body.data.refreshToken.access_token).toBe( 166 + "string", 167 + ); 168 + expect(typeof response.body.data.refreshToken.refresh_token).toBe( 169 + "string", 170 + ); 171 + 172 + // Update tokens for next test 173 + accessToken = response.body.data.refreshToken.access_token; 174 + refreshToken = response.body.data.refreshToken.refresh_token; 175 + }); 176 + 177 + it("should fail with invalid refresh token", async () => { 178 + const refreshMutation = ` 179 + mutation RefreshToken($refresh_token: String!) { 180 + refreshToken(refresh_token: $refresh_token) { 181 + access_token 182 + refresh_token 183 + expires_at 184 + } 185 + } 186 + `; 187 + 188 + const response = await request(app.getHttpServer()) 189 + .post("/graphql") 190 + .send({ 191 + query: refreshMutation, 192 + variables: { 193 + refresh_token: "invalid-token", 194 + }, 195 + }) 196 + .expect(200); 197 + 198 + expect(response.body.errors).toBeDefined(); 199 + expect(response.body.errors[0].message).toContain( 200 + "Invalid or expired refresh token", 201 + ); 202 + }); 203 + 204 + it("should fail when using access token as refresh token", async () => { 205 + const refreshMutation = ` 206 + mutation RefreshToken($refresh_token: String!) { 207 + refreshToken(refresh_token: $refresh_token) { 208 + access_token 209 + refresh_token 210 + expires_at 211 + } 212 + } 213 + `; 214 + 215 + const response = await request(app.getHttpServer()) 216 + .post("/graphql") 217 + .send({ 218 + query: refreshMutation, 219 + variables: { 220 + refresh_token: accessToken, // Using access token instead of refresh token 221 + }, 222 + }) 223 + .expect(200); 224 + 225 + expect(response.body.errors).toBeDefined(); 226 + expect(response.body.errors[0].message).toContain( 227 + "Invalid or expired refresh token", 228 + ); 229 + }); 230 + }); 231 + 232 + describe("Protected Route with Refreshed Token", () => { 233 + it("should access protected route with new access token", async () => { 234 + const meQuery = ` 235 + query Me { 236 + me { 237 + id 238 + email 239 + name 240 + } 241 + } 242 + `; 243 + 244 + const response = await request(app.getHttpServer()) 245 + .post("/graphql") 246 + .set("Authorization", `Bearer ${accessToken}`) 247 + .send({ 248 + query: meQuery, 249 + }) 250 + .expect(200); 251 + 252 + expect(response.body.errors).toBeUndefined(); 253 + expect(response.body.data.me).toBeDefined(); 254 + expect(response.body.data.me.email).toBeDefined(); 255 + }); 256 + }); 257 + 258 + describe("Token Expiry Validation", () => { 259 + it("should return expiry time in ISO 8601 format", async () => { 260 + const registerMutation = ` 261 + mutation Register($name: String!, $email: String!, $password: String!) { 262 + register(name: $name, email: $email, password: $password) { 263 + expires_at 264 + } 265 + } 266 + `; 267 + 268 + const response = await request(app.getHttpServer()) 269 + .post("/graphql") 270 + .send({ 271 + query: registerMutation, 272 + variables: { 273 + name: "Expiry Test User", 274 + email: `expiry-test-${Date.now()}@example.com`, 275 + password: "password123", 276 + }, 277 + }) 278 + .expect(200); 279 + 280 + const expiryDate = new Date(response.body.data.register.expires_at); 281 + 282 + // Should be a valid date 283 + expect(expiryDate.toString()).not.toBe("Invalid Date"); 284 + 285 + // Should be in the future 286 + expect(expiryDate.getTime()).toBeGreaterThan(Date.now()); 287 + 288 + // Should be approximately 15 minutes in the future (default config) 289 + const fifteenMinutesFromNow = Date.now() + 15 * 60 * 1000; 290 + const timeDiff = Math.abs(expiryDate.getTime() - fifteenMinutesFromNow); 291 + 292 + // Allow 10 seconds tolerance for test execution time 293 + expect(timeDiff).toBeLessThan(10000); 294 + }); 295 + }); 296 + });
+1 -1
apps/server/test/coverage-unit/lcov-report/index.html
··· 86 86 <div class='footer quiet pad2 space-top1 center small'> 87 87 Code coverage generated by 88 88 <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a> 89 - at 2025-10-20T15:57:14.900Z 89 + at 2025-11-03T21:19:29.728Z 90 90 </div> 91 91 <script src="prettify.js"></script> 92 92 <script>
+327
apps/server/test/pagination-integration.e2e-spec.ts
··· 1 + import type { INestApplication } from "@nestjs/common"; 2 + import { 3 + COMPANIES_PAGINATION_QUERY, 4 + LEVELS_PAGINATION_QUERY, 5 + ROLES_PAGINATION_QUERY, 6 + SKILLS_PAGINATION_QUERY, 7 + } from "./queries/load-queries"; 8 + import { makeUnauthenticatedRequest, setupTestApp } from "./test-utils"; 9 + 10 + describe("Pagination Integration Tests (e2e)", () => { 11 + let app: INestApplication; 12 + 13 + beforeAll(async () => { 14 + app = await setupTestApp(); 15 + }); 16 + 17 + afterAll(async () => { 18 + await app.close(); 19 + }); 20 + 21 + describe("Skills Pagination", () => { 22 + it("should return skills with pagination info", async () => { 23 + const response = await makeUnauthenticatedRequest(app) 24 + .send({ 25 + query: SKILLS_PAGINATION_QUERY, 26 + variables: { 27 + first: 5, 28 + }, 29 + }) 30 + .expect(200); 31 + 32 + expect(response.body.data.skills).toBeDefined(); 33 + expect(response.body.data.skills.edges).toBeDefined(); 34 + expect(Array.isArray(response.body.data.skills.edges)).toBe(true); 35 + expect(response.body.data.skills.pageInfo).toBeDefined(); 36 + expect(response.body.data.skills.pageInfo.hasNextPage).toBeDefined(); 37 + expect(response.body.data.skills.pageInfo.hasPreviousPage).toBeDefined(); 38 + expect(response.body.data.skills.totalCount).toBeDefined(); 39 + expect(typeof response.body.data.skills.totalCount).toBe("number"); 40 + }); 41 + 42 + it("should handle cursor-based pagination", async () => { 43 + // Get first page 44 + const firstPageResponse = await makeUnauthenticatedRequest(app) 45 + .send({ 46 + query: SKILLS_PAGINATION_QUERY, 47 + variables: { 48 + first: 3, 49 + }, 50 + }) 51 + .expect(200); 52 + 53 + const firstPage = firstPageResponse.body.data.skills; 54 + expect(firstPage.edges).toHaveLength(3); 55 + expect(firstPage.pageInfo.hasNextPage).toBeDefined(); 56 + 57 + // If there's a next page, get it using the cursor 58 + if (firstPage.pageInfo.hasNextPage) { 59 + const secondPageResponse = await makeUnauthenticatedRequest(app) 60 + .send({ 61 + query: SKILLS_PAGINATION_QUERY, 62 + variables: { 63 + first: 3, 64 + after: firstPage.pageInfo.endCursor, 65 + }, 66 + }) 67 + .expect(200); 68 + 69 + const secondPage = secondPageResponse.body.data.skills; 70 + expect(secondPage.edges).toBeDefined(); 71 + expect(Array.isArray(secondPage.edges)).toBe(true); 72 + 73 + // Ensure we get different results 74 + const firstPageIds = firstPage.edges.map( 75 + (edge: { node: { id: string } }) => edge.node.id, 76 + ); 77 + const secondPageIds = secondPage.edges.map( 78 + (edge: { node: { id: string } }) => edge.node.id, 79 + ); 80 + const hasOverlap = firstPageIds.some((id: string) => 81 + secondPageIds.includes(id), 82 + ); 83 + expect(hasOverlap).toBe(false); 84 + } 85 + }); 86 + 87 + it("should handle search term filtering", async () => { 88 + const response = await makeUnauthenticatedRequest(app) 89 + .send({ 90 + query: SKILLS_PAGINATION_QUERY, 91 + variables: { 92 + first: 10, 93 + searchTerm: "JavaScript", // Assuming this skill exists 94 + }, 95 + }) 96 + .expect(200); 97 + 98 + expect(response.body.data.skills).toBeDefined(); 99 + expect(response.body.data.skills.edges).toBeDefined(); 100 + expect(Array.isArray(response.body.data.skills.edges)).toBe(true); 101 + }); 102 + 103 + it("should return empty results for non-existent search term", async () => { 104 + const response = await makeUnauthenticatedRequest(app) 105 + .send({ 106 + query: SKILLS_PAGINATION_QUERY, 107 + variables: { 108 + first: 10, 109 + searchTerm: "NonExistentSkill12345", 110 + }, 111 + }) 112 + .expect(200); 113 + 114 + expect(response.body.data.skills).toBeDefined(); 115 + expect(response.body.data.skills.edges).toHaveLength(0); 116 + expect(response.body.data.skills.totalCount).toBe(0); 117 + expect(response.body.data.skills.pageInfo.hasNextPage).toBe(false); 118 + }); 119 + }); 120 + 121 + describe("Companies Pagination", () => { 122 + it("should return companies with pagination info", async () => { 123 + const response = await makeUnauthenticatedRequest(app) 124 + .send({ 125 + query: COMPANIES_PAGINATION_QUERY, 126 + }) 127 + .expect(200); 128 + 129 + expect(response.body.data.companies).toBeDefined(); 130 + expect(response.body.data.companies.edges).toBeDefined(); 131 + expect(Array.isArray(response.body.data.companies.edges)).toBe(true); 132 + expect(response.body.data.companies.pageInfo).toBeDefined(); 133 + expect(response.body.data.companies.totalCount).toBeDefined(); 134 + expect(typeof response.body.data.companies.totalCount).toBe("number"); 135 + }); 136 + 137 + it("should handle search term filtering for companies", async () => { 138 + const response = await makeUnauthenticatedRequest(app) 139 + .send({ 140 + query: COMPANIES_PAGINATION_QUERY, 141 + variables: { 142 + searchTerm: "Test", // Assuming test companies exist 143 + }, 144 + }) 145 + .expect(200); 146 + 147 + expect(response.body.data.companies).toBeDefined(); 148 + expect(response.body.data.companies.edges).toBeDefined(); 149 + expect(Array.isArray(response.body.data.companies.edges)).toBe(true); 150 + }); 151 + }); 152 + 153 + describe("Roles Pagination", () => { 154 + it("should return roles with pagination info", async () => { 155 + const response = await makeUnauthenticatedRequest(app) 156 + .send({ 157 + query: ROLES_PAGINATION_QUERY, 158 + }) 159 + .expect(200); 160 + 161 + expect(response.body.data.roles).toBeDefined(); 162 + expect(response.body.data.roles.edges).toBeDefined(); 163 + expect(Array.isArray(response.body.data.roles.edges)).toBe(true); 164 + expect(response.body.data.roles.pageInfo).toBeDefined(); 165 + expect(response.body.data.roles.totalCount).toBeDefined(); 166 + expect(typeof response.body.data.roles.totalCount).toBe("number"); 167 + }); 168 + 169 + it("should handle search term filtering for roles", async () => { 170 + const response = await makeUnauthenticatedRequest(app) 171 + .send({ 172 + query: ROLES_PAGINATION_QUERY, 173 + variables: { 174 + searchTerm: "Developer", // Assuming this role exists 175 + }, 176 + }) 177 + .expect(200); 178 + 179 + expect(response.body.data.roles).toBeDefined(); 180 + expect(response.body.data.roles.edges).toBeDefined(); 181 + expect(Array.isArray(response.body.data.roles.edges)).toBe(true); 182 + }); 183 + }); 184 + 185 + describe("Levels Pagination", () => { 186 + it("should return levels with pagination info", async () => { 187 + const response = await makeUnauthenticatedRequest(app) 188 + .send({ 189 + query: LEVELS_PAGINATION_QUERY, 190 + }) 191 + .expect(200); 192 + 193 + expect(response.body.data.levels).toBeDefined(); 194 + expect(response.body.data.levels.edges).toBeDefined(); 195 + expect(Array.isArray(response.body.data.levels.edges)).toBe(true); 196 + expect(response.body.data.levels.pageInfo).toBeDefined(); 197 + expect(response.body.data.levels.totalCount).toBeDefined(); 198 + expect(typeof response.body.data.levels.totalCount).toBe("number"); 199 + }); 200 + 201 + it("should handle search term filtering for levels", async () => { 202 + const response = await makeUnauthenticatedRequest(app) 203 + .send({ 204 + query: LEVELS_PAGINATION_QUERY, 205 + variables: { 206 + searchTerm: "Senior", // Assuming this level exists 207 + }, 208 + }) 209 + .expect(200); 210 + 211 + expect(response.body.data.levels).toBeDefined(); 212 + expect(response.body.data.levels.edges).toBeDefined(); 213 + expect(Array.isArray(response.body.data.levels.edges)).toBe(true); 214 + }); 215 + }); 216 + 217 + describe("Pagination Edge Cases", () => { 218 + it("should handle zero limit gracefully", async () => { 219 + const response = await makeUnauthenticatedRequest(app) 220 + .send({ 221 + query: SKILLS_PAGINATION_QUERY, 222 + variables: { 223 + first: 0, 224 + }, 225 + }) 226 + .expect(200); 227 + 228 + expect(response.body.data.skills).toBeDefined(); 229 + expect(response.body.data.skills.edges).toHaveLength(0); 230 + expect(response.body.data.skills.pageInfo.hasNextPage).toBe(false); 231 + }); 232 + 233 + it("should handle large limit gracefully", async () => { 234 + const response = await makeUnauthenticatedRequest(app) 235 + .send({ 236 + query: SKILLS_PAGINATION_QUERY, 237 + variables: { 238 + first: 1000, 239 + }, 240 + }) 241 + .expect(200); 242 + 243 + expect(response.body.data.skills).toBeDefined(); 244 + expect(response.body.data.skills.edges).toBeDefined(); 245 + expect(Array.isArray(response.body.data.skills.edges)).toBe(true); 246 + }); 247 + 248 + it("should handle invalid cursor gracefully", async () => { 249 + const response = await makeUnauthenticatedRequest(app) 250 + .send({ 251 + query: SKILLS_PAGINATION_QUERY, 252 + variables: { 253 + first: 5, 254 + after: "invalid-cursor", 255 + }, 256 + }) 257 + .expect(200); 258 + 259 + // Should either return empty results or handle gracefully 260 + expect(response.body.data.skills).toBeDefined(); 261 + expect(response.body.data.skills.edges).toBeDefined(); 262 + expect(Array.isArray(response.body.data.skills.edges)).toBe(true); 263 + }); 264 + }); 265 + 266 + describe("Pagination Consistency", () => { 267 + it("should maintain consistent total count across pages", async () => { 268 + const firstPageResponse = await makeUnauthenticatedRequest(app) 269 + .send({ 270 + query: SKILLS_PAGINATION_QUERY, 271 + variables: { 272 + first: 2, 273 + }, 274 + }) 275 + .expect(200); 276 + 277 + const firstPage = firstPageResponse.body.data.skills; 278 + const totalCount = firstPage.totalCount; 279 + 280 + if (firstPage.pageInfo.hasNextPage) { 281 + const secondPageResponse = await makeUnauthenticatedRequest(app) 282 + .send({ 283 + query: SKILLS_PAGINATION_QUERY, 284 + variables: { 285 + first: 2, 286 + after: firstPage.pageInfo.endCursor, 287 + }, 288 + }) 289 + .expect(200); 290 + 291 + const secondPage = secondPageResponse.body.data.skills; 292 + expect(secondPage.totalCount).toBe(totalCount); 293 + } 294 + }); 295 + 296 + it("should have valid cursor format", async () => { 297 + const response = await makeUnauthenticatedRequest(app) 298 + .send({ 299 + query: SKILLS_PAGINATION_QUERY, 300 + variables: { 301 + first: 5, 302 + }, 303 + }) 304 + .expect(200); 305 + 306 + const skills = response.body.data.skills; 307 + 308 + // Check that all edges have valid cursors 309 + skills.edges.forEach((edge: { cursor: string; node: { id: string } }) => { 310 + expect(edge.cursor).toBeDefined(); 311 + expect(typeof edge.cursor).toBe("string"); 312 + expect(edge.cursor.length).toBeGreaterThan(0); 313 + }); 314 + 315 + // Check that pageInfo cursors are valid when present 316 + if (skills.pageInfo.startCursor) { 317 + expect(typeof skills.pageInfo.startCursor).toBe("string"); 318 + expect(skills.pageInfo.startCursor.length).toBeGreaterThan(0); 319 + } 320 + 321 + if (skills.pageInfo.endCursor) { 322 + expect(typeof skills.pageInfo.endCursor).toBe("string"); 323 + expect(skills.pageInfo.endCursor.length).toBeGreaterThan(0); 324 + } 325 + }); 326 + }); 327 + });
+22
apps/server/test/queries/companies-pagination-query.graphql
··· 1 + query CompaniesPagination($searchTerm: String) { 2 + companies(searchTerm: $searchTerm) { 3 + edges { 4 + cursor 5 + node { 6 + id 7 + name 8 + description 9 + website 10 + createdAt 11 + updatedAt 12 + } 13 + } 14 + pageInfo { 15 + hasNextPage 16 + hasPreviousPage 17 + startCursor 18 + endCursor 19 + } 20 + totalCount 21 + } 22 + }
+21
apps/server/test/queries/levels-pagination-query.graphql
··· 1 + query LevelsPagination($searchTerm: String) { 2 + levels(searchTerm: $searchTerm) { 3 + edges { 4 + cursor 5 + node { 6 + id 7 + name 8 + description 9 + createdAt 10 + updatedAt 11 + } 12 + } 13 + pageInfo { 14 + hasNextPage 15 + hasPreviousPage 16 + startCursor 17 + endCursor 18 + } 19 + totalCount 20 + } 21 + }
+14
apps/server/test/queries/load-queries.ts
··· 42 42 export const ALL_ROLES_QUERY = readGraphQLFile("all-roles-query.graphql"); 43 43 export const ALL_LEVELS_QUERY = readGraphQLFile("all-levels-query.graphql"); 44 44 45 + // Pagination queries 46 + export const SKILLS_PAGINATION_QUERY = readGraphQLFile( 47 + "skills-pagination-query.graphql", 48 + ); 49 + export const COMPANIES_PAGINATION_QUERY = readGraphQLFile( 50 + "companies-pagination-query.graphql", 51 + ); 52 + export const ROLES_PAGINATION_QUERY = readGraphQLFile( 53 + "roles-pagination-query.graphql", 54 + ); 55 + export const LEVELS_PAGINATION_QUERY = readGraphQLFile( 56 + "levels-pagination-query.graphql", 57 + ); 58 + 45 59 // Additional queries extracted from inline usage 46 60 export const CREATE_COMPANY_MUTATION = readGraphQLFile( 47 61 "create-company-mutation.graphql",
+21
apps/server/test/queries/roles-pagination-query.graphql
··· 1 + query RolesPagination($searchTerm: String) { 2 + roles(searchTerm: $searchTerm) { 3 + edges { 4 + cursor 5 + node { 6 + id 7 + name 8 + description 9 + createdAt 10 + updatedAt 11 + } 12 + } 13 + pageInfo { 14 + hasNextPage 15 + hasPreviousPage 16 + startCursor 17 + endCursor 18 + } 19 + totalCount 20 + } 21 + }
+21
apps/server/test/queries/skills-pagination-query.graphql
··· 1 + query SkillsPagination($first: Int, $after: String, $searchTerm: String) { 2 + skills(first: $first, after: $after, searchTerm: $searchTerm) { 3 + edges { 4 + cursor 5 + node { 6 + id 7 + name 8 + description 9 + createdAt 10 + updatedAt 11 + } 12 + } 13 + pageInfo { 14 + hasNextPage 15 + hasPreviousPage 16 + startCursor 17 + endCursor 18 + } 19 + totalCount 20 + } 21 + }