Initial commit

This commit is contained in:
Zhongwei Li
2025-11-30 08:22:57 +08:00
commit 12a5ba6a10
11 changed files with 770 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
# Assets
Bundled resources for api-test-automation skill
- [ ] test_suite_template.js: Template for generating API test suites, including placeholders for different test cases and assertions.
- [ ] example_openapi.yaml: Example OpenAPI specification file for demonstration and testing purposes.
- [ ] example_graphql_schema.graphql: Example GraphQL schema file for testing GraphQL APIs.

View File

@@ -0,0 +1,98 @@
# Example GraphQL schema file for testing GraphQL APIs.
# This schema defines a simple book catalog with authors.
# Types
type Book {
id: ID!
title: String!
author: Author!
publicationYear: Int
genre: String
}
type Author {
id: ID!
name: String!
books: [Book!]!
}
# Queries
type Query {
# Get a book by its ID
book(id: ID!): Book
# Get all books
books: [Book!]!
# Get an author by their ID
author(id: ID!): Author
# Get all authors
authors: [Author!]!
# Search for books by title or author name
search(query: String!): [Book!]!
}
# Mutations
type Mutation {
# Create a new book
createBook(
title: String!
authorId: ID!
publicationYear: Int
genre: String
): Book
# Update an existing book
updateBook(
id: ID!
title: String
authorId: ID
publicationYear: Int
genre: String
): Book
# Delete a book by its ID
deleteBook(id: ID!): ID
# Create a new author
createAuthor(name: String!): Author
}
# Input types (optional, for more complex mutations)
# input CreateBookInput {
# title: String!
# authorId: ID!
# publicationYear: Int
# genre: String
# }
# Placeholder for subscriptions (if needed)
# type Subscription {
# newBook: Book
# }
# Further instructions:
# 1. This is a basic example. Extend it with more complex types, fields, and relationships as needed.
# 2. Consider adding input types for mutations to improve clarity and validation.
# 3. Implement resolvers for each query and mutation to connect to your data source.
# 4. Use directives for authorization, caching, and other features.
# 5. Use scalars for custom data types (e.g., Date, URL).
# 6. Example query to get a specific book:
# query {
# book(id: "123") {
# id
# title
# author {
# name
# }
# }
# }
# 7. Example mutation to create a book:
# mutation {
# createBook(title: "New Book", authorId: "456", publicationYear: 2023, genre: "Fiction") {
# id
# title
# }
# }

View File

@@ -0,0 +1,216 @@
# OpenAPI Specification for Example API
openapi: 3.0.0
info:
title: Example API
version: 1.0.0
description: A sample API for demonstration purposes.
termsOfService: REPLACE_ME # Add your terms of service URL here
contact:
name: API Support
url: REPLACE_ME # Add your support URL here
email: support@example.com
license:
name: Apache 2.0
url: https://www.apache.org/licenses/LICENSE-2.0.html
servers:
- url: https://api.example.com/v1
description: Production server
paths:
/users:
get:
summary: Get all users
description: Retrieves a list of all users.
operationId: getUsers
tags:
- users
responses:
'200':
description: Successful operation
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/User'
'500':
description: Internal server error
post:
summary: Create a new user
description: Creates a new user in the system.
operationId: createUser
tags:
- users
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UserCreate'
responses:
'201':
description: User created successfully
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'400':
description: Bad request
'500':
description: Internal server error
/users/{userId}:
get:
summary: Get user by ID
description: Retrieves a user by their ID.
operationId: getUserById
tags:
- users
parameters:
- name: userId
in: path
description: ID of the user to retrieve.
required: true
schema:
type: integer
format: int64
responses:
'200':
description: Successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'404':
description: User not found
'500':
description: Internal server error
put:
summary: Update user by ID
description: Updates an existing user.
operationId: updateUser
tags:
- users
parameters:
- name: userId
in: path
description: ID of the user to update.
required: true
schema:
type: integer
format: int64
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UserUpdate'
responses:
'200':
description: Successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'400':
description: Bad request
'404':
description: User not found
'500':
description: Internal server error
delete:
summary: Delete user by ID
description: Deletes a user by their ID.
operationId: deleteUser
tags:
- users
parameters:
- name: userId
in: path
description: ID of the user to delete.
required: true
schema:
type: integer
format: int64
responses:
'204':
description: User deleted successfully (No Content)
'404':
description: User not found
'500':
description: Internal server error
components:
schemas:
User:
type: object
properties:
id:
type: integer
format: int64
description: Unique identifier for the user
username:
type: string
description: User's username
email:
type: string
format: email
description: User's email address
firstName:
type: string
description: User's first name
lastName:
type: string
description: User's last name
required:
- id
- username
- email
UserCreate:
type: object
properties:
username:
type: string
description: User's username
email:
type: string
format: email
description: User's email address
firstName:
type: string
description: User's first name
lastName:
type: string
description: User's last name
required:
- username
- email
UserUpdate:
type: object
properties:
username:
type: string
description: User's username
email:
type: string
format: email
description: User's email address
firstName:
type: string
description: User's first name
lastName:
type: string
description: User's last name
securitySchemes:
bearerAuth: # Define security scheme name
type: http
scheme: bearer
bearerFormat: JWT
security:
- bearerAuth: [] # Apply the security scheme to all endpoints (globally)

View File

@@ -0,0 +1,99 @@
/**
* test_suite_template.js
*
* Template for generating API test suites. This template provides a structure
* for creating comprehensive test cases for various API endpoints.
*
* @example
* // Example usage (after replacing placeholders):
* const testSuite = require('./test_suite_template');
*
* const config = {
* baseURL: 'https://api.example.com',
* endpoint: '/users',
* method: 'GET',
* description: 'Retrieve all users'
* };
*
* const testCase = testSuite(config);
*
* describe(config.description, () => {
* it('should return a 200 OK status', async () => {
* const response = await testCase.request();
* expect(response.status).toBe(200);
* });
* // Add more test cases here...
* });
*/
/**
* Generates a test suite based on the provided configuration.
*
* @param {object} config - Configuration object for the test suite.
* @param {string} config.baseURL - The base URL of the API.
* @param {string} config.endpoint - The API endpoint to test.
* @param {string} config.method - The HTTP method to use (GET, POST, PUT, DELETE, etc.).
* @param {string} config.description - A description of the test case.
* @param {object} [config.headers] - Optional headers to include in the request.
* @param {object} [config.body] - Optional request body.
* @param {string} [config.authenticationType] - Optional authentication type (e.g., 'Bearer', 'OAuth', 'API Key').
* @param {string} [config.authenticationToken] - Optional authentication token or API key.
* @returns {object} An object containing the request function.
*/
module.exports = (config) => {
const axios = require('axios'); // Consider making axios a configurable dependency if needed
/**
* Executes the API request based on the configuration.
*
* @async
* @function request
* @returns {Promise<object>} A promise that resolves to the API response.
* @throws {Error} If the request fails.
*/
async function request() {
try {
const requestConfig = {
method: config.method,
url: config.baseURL + config.endpoint,
headers: config.headers || {},
data: config.body || null, // Use data for POST/PUT requests, params for GET
// params: config.method === 'GET' ? config.body : null // Alternate: use params for GET requests
};
// Authentication handling
if (config.authenticationType === 'Bearer' && config.authenticationToken) {
requestConfig.headers.Authorization = `Bearer ${config.authenticationToken}`;
} else if (config.authenticationType === 'API Key' && config.authenticationToken) {
// Example API Key header - adjust based on API requirements
requestConfig.headers['X-API-Key'] = config.authenticationToken;
} // Add more authentication types as needed
const response = await axios(requestConfig);
return response;
} catch (error) {
// Handle errors appropriately (e.g., log, re-throw, or return a custom error object)
console.error(`Request failed for ${config.description}:`, error.message);
throw error; // Re-throw the error for the test to handle
}
}
return {
request,
// Add more helper functions here if needed (e.g., for data validation)
validateResponseSchema: (response, schema) => {
// Placeholder: Implement schema validation logic using a library like Joi or Ajv
// Example:
// const validationResult = schema.validate(response.data);
// if (validationResult.error) {
// throw new Error(`Schema validation failed: ${validationResult.error.message}`);
// }
},
extractDataFromResponse: (response, path) => {
// Placeholder: Implement logic to extract data from the response using a library like lodash.get
// Example:
// return _.get(response.data, path);
}
};
};