Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ Use `expect(actual_value)` with assertions:

`only()` Declares an exclusive test or test group that will be executed. If used, all other tests are skipped.

`todo()` Declares a test or test group as "to-do." The test(s) is/are marked as pending and will not be executed. Helpful for planning and organizing future tests.

### `Example↓`


Expand All @@ -181,6 +183,14 @@ describe.only('description', () => {
})
```

```js
test.todo('description')
//or
describe.todo('description', () => {
// This test group is a placeholder and won't run
})
```

---

## Context options
Expand Down
70 changes: 51 additions & 19 deletions src/core/context.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const result = {
numTests: 0,
numPassed: 0,
numFailed: 0,
numTodo: 0,
results: [],
}

Expand Down Expand Up @@ -59,18 +60,24 @@ export const describe = (name, optionsOrBody, body) => {
}
}

describe.only = (name, optionsOrBody, body) => {
const options = typeof optionsOrBody === 'object' ? optionsOrBody : {}
const actualBody = typeof optionsOrBody === 'function' ? optionsOrBody : body
const parentDescribe = currentDescribe
currentDescribe = makeDescribe(name, { ...options, focus: true })
actualBody()
currentDescribe = {
...parentDescribe,
children: [...parentDescribe.children, currentDescribe],
function createDescribeVariant(extra) {
return (name, optionsOrBody, body) => {
const options = typeof optionsOrBody === 'object' ? optionsOrBody : {}
const actualBody = typeof optionsOrBody === 'function' ? optionsOrBody : body
const parentDescribe = currentDescribe
currentDescribe = makeDescribe(name, { ...options, ...extra })
// Для todo не викликаємо body
if (!extra.todo) actualBody?.()
currentDescribe = {
...parentDescribe,
children: [...parentDescribe.children, currentDescribe],
}
}
}

describe.only = createDescribeVariant({ focus: true })
describe.todo = createDescribeVariant({ todo: true })

export const test = (name, optionsOrBody, body) => {
const options = typeof optionsOrBody === 'object' ? optionsOrBody : {}
const actualBody = typeof optionsOrBody === 'function' ? optionsOrBody : body
Expand All @@ -83,18 +90,32 @@ export const test = (name, optionsOrBody, body) => {
}
}

test.only = (name, optionsOrBody, body) => {
const options = typeof optionsOrBody === 'object' ? optionsOrBody : {}
const actualBody = typeof optionsOrBody === 'function' ? optionsOrBody : body
currentDescribe = {
...currentDescribe,
children: [
...currentDescribe.children,
{ ...makeTest(name, actualBody, options.timeout, options.tags, options.retry), focus: true },
],
function createTestVariant(extra) {
return (name, optionsOrBody, body) => {
const options = typeof optionsOrBody === 'object' ? optionsOrBody : {}
const actualBody = typeof optionsOrBody === 'function' ? optionsOrBody : body
currentDescribe = {
...currentDescribe,
children: [
...currentDescribe.children,
{
...makeTest(
name,
extra.todo ? () => {} : actualBody,
options.timeout,
options.tags,
options.retry
),
...extra,
},
],
}
}
}

test.only = createTestVariant({ focus: true })
test.todo = createTestVariant({ todo: true })

export const skip = (name) => {
printSkippedMsg(name)
}
Expand Down Expand Up @@ -179,7 +200,18 @@ const runTest = async (test) => {
}
attempts++
}
if (!passed) {
if (test.skip) {
result.numSkipped++
console.log(
indent(applyColor(`<cyan>⏸</cyan> ${currentTest.name} (SKIPPED)`))
)
}
if (test.todo) {
result.numTodo++
console.log(
indent(applyColor(`<yellow>◦</yellow> ${currentTest.name} (TODO)`))
)
} else if (!passed) {
result.numFailed++
console.log(indent(applyColor(`<red>✗</red> ${currentTest.name}`)))
failures.push(currentTest)
Expand Down
94 changes: 61 additions & 33 deletions src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ type Options = {
* });
* ```
* or
*
* * ```js
* ```js
* describe('example', () => {
* test.skip('skipped test', () => {
* // This test will not run
Expand All @@ -67,10 +66,11 @@ type Options = {
*
* @param name Test title.
* @param optionsOrBody (Optional) Object with options
* @param callback A callback that is run immediately when calling test(name, optionsOrBody, callback)
* @param body A callback that is linked to the skipped test
*/
skip(name: string, optionsOrBody: {}, body: {}): void
/**
skip(name: string, optionsOrBody?: {}, body?: {}): void

/**
* Declares an exclusive test group.
* Only the tests in this group are run, and all other tests are skipped.
* - `describe.only(title)`
Expand All @@ -87,7 +87,6 @@ type Options = {
* });
* ```
* or
*
* ```js
* describe('example', () => {
* test.only('focused test', () => {
Expand All @@ -98,9 +97,38 @@ type Options = {
*
* @param name Test title.
* @param optionsOrBody (Optional) Object with options
* @param callback A callback that is run immediately when calling test(name, optionsOrBody, callback)
* @param body A callback that is linked to the exclusive test
*/
only(name: string, optionsOrBody?: {}, body?: {}): void;
only(name: string, optionsOrBody?: {}, body?: {}): void

/**
* Declares a test as "to-do".
* Marks the test or test group as a placeholder for future implementation, but does not execute it.
* - `test.todo(title)`
* - `describe.todo(title)`
*
* **Usage**
*
* Marking individual tests as "to-do":
* ```js
* test.todo('Test for input validation');
* test.todo('Handle edge cases for user roles');
* ```
*
* Marking a test group as "to-do":
* ```js
* describe.todo('User Profile Tests', () => {
* // Placeholder for future tests
* });
* ```
*
* **Terminal Output**
* Tests marked as `todo` will appear in the output as pending, without causing failures.
*
* @param name Test or group title.
* @param optionsOrBody (Optional) Object with additional options
*/
todo(name: string, optionsOrBody?: {}): void
}
/**
* Execute before each test case.
Expand Down Expand Up @@ -333,33 +361,33 @@ export function expect(expected: any): Assertions
*/
export interface Response {
/** Boolean indicating if the response was successful (status in the range 200-299) */
ok: boolean;
ok: boolean
/** The status code of the response (e.g., 200 for success, 404 for not found) */
status: number;
status: number
/** The status message associated with the status code */
statusText: string;
statusText: string
/** Indicates whether or not the response is the result of a redirect */
redirected: boolean;
redirected: boolean
/** The type of the response (e.g., 'basic', 'cors', 'error') */
type: string;
type: string
/** The URL of the response */
url: string;
url: string
/** The headers associated with the response */
headers: Headers;
headers: Headers
/** Indicates whether the body has been read yet */
bodyUsed: boolean;
bodyUsed: boolean
/** Returns a promise that resolves with an ArrayBuffer representation of the body */
arrayBuffer(): Promise<ArrayBuffer>;
arrayBuffer(): Promise<ArrayBuffer>
/** Returns a promise that resolves with a Blob representation of the body */
blob(): Promise<Blob>;
blob(): Promise<Blob>
/** Returns a promise that resolves with a FormData representation of the body */
formData(): Promise<FormData>;
formData(): Promise<FormData>
/** Returns a promise that resolves with the result of parsing the body text as JSON */
json(): Promise<any>;
json(): Promise<any>
/** Returns a promise that resolves with the body text */
text(): Promise<string>;
text(): Promise<string>
/** Creates a clone of the response object */
clone(): Response;
clone(): Response
}

/**
Expand Down Expand Up @@ -393,7 +421,7 @@ export interface Response {
export const request: {
/**
* Sends a GET request to the specified URL and returns a Response object.
*
*
* @param url - The URL to send the GET request to
* @param config - Optional request configuration
* @returns A promise that resolves to a Response object
Expand All @@ -412,33 +440,33 @@ export const request: {
* }
* });
*/
get(url: string, config?: RequestInit): Promise<Response>;
get(url: string, config?: RequestInit): Promise<Response>

/**
* Sends a POST request with JSON body to the specified URL
* @param url The URL to send the POST request to
* @param config Optional request configuration
*/
post(url: string, config?: RequestInit): Promise<Response>;
post(url: string, config?: RequestInit): Promise<Response>

/**
* Sends a PUT request with JSON body to the specified URL
* @param url The URL to send the PUT request to
* @param config Optional request configuration
*/
put(url: string, config?: RequestInit): Promise<Response>;
put(url: string, config?: RequestInit): Promise<Response>

/**
* Sends a PATCH request with JSON body to the specified URL
* @param url The URL to send the PATCH request to
* @param config Optional request configuration
*/
patch(url: string, config?: RequestInit): Promise<Response>;
patch(url: string, config?: RequestInit): Promise<Response>

/**
* Sends a DELETE request to the specified URL
* @param url The URL to send the DELETE request to
* @param config Optional request configuration
*/
delete(url: string, config?: RequestInit): Promise<Response>;
};
delete(url: string, config?: RequestInit): Promise<Response>
}
60 changes: 60 additions & 0 deletions src/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,38 @@ describe.skip = (name) => core.skip(name)
*/
describe.only = (...args) => core.describe.only(...args)

/**
* Declares a test group as "to-do".
* Marks the entire group of tests as a placeholder for future implementation but does not execute it.
* Useful for keeping track of large features or modules that require further testing.
* - `describe.todo(title)`
*
* **Usage**
*
* Marking a test group as "to-do":
*
* ```js
* describe.todo('Feature: User Authentication Tests', () => {
* // Placeholder for tests related to user authentication
* });
* ```
*
* Practical example:
* ```js
* describe.todo('API Endpoint Tests', () => {
* test.todo('Test GET /users endpoint');
* test.todo('Test POST /users endpoint');
* });
* ```
*
* **Terminal Output**
* When running the test suite, `describe.todo` groups and their respective `test.todo` entries will appear in the results as pending, without causing failures or executions.
*
* @param name Group title.
* @param optionsOrBody (Optional) Object with options
* @param callback (Optional) A callback function to define additional structure inside the group.
*/
describe.todo = (...args) => core.describe.todo(...args)
/**
* Test a specification or test-case with the given title, test options and callback fn.
*
Expand Down Expand Up @@ -126,6 +158,34 @@ test.skip = (name) => core.skip(name)
*/
test.only = (...args) => core.test.only(...args)

/**
* Declares a test as "to-do".
* Marks the test as a placeholder for future implementation but doesn't execute it.
* This can be useful for tracking incomplete test cases or reminders for future work.
* - `test.todo(title)`
*
* **Usage**
*
* Marking individual tests as "to-do":
*
* ```js
* test.todo('Add validation for input data');
* test.todo('Test error handling for invalid user sessions');
* ```
*
* Practical example:
* ```js
* test.todo('Implement edge case handling for data overflow');
* test.todo('Add tests for login timeout scenarios');
* ```
*
* **Terminal Output**
* When running the test suite, `test.todo` tests will appear in the results as pending, but they will not fail or be executed.
*
* @param name Test title.
*/
test.todo = (...args) => core.test.todo(...args)

/**
* Execute before each test case.
*
Expand Down
Loading