mirror of
https://github.com/hashicorp/vault.git
synced 2026-02-03 20:40:45 -05:00
* add copilot instructions to repository use copilot resources example repo (https://github.com/hashicorp/copilot-resources/tree/main) * address PR comments (https://github.com/hashicorp/vault/pull/31361) Co-authored-by: Shannon Roberts (Beagin) <beagins@users.noreply.github.com>
This commit is contained in:
parent
2b469deeca
commit
e47c5b5e39
9 changed files with 810 additions and 0 deletions
88
.github/instructions/generic/ember_general.instructions.md
vendored
Normal file
88
.github/instructions/generic/ember_general.instructions.md
vendored
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
---
|
||||
applyTo: "vault/ui/**/*"
|
||||
description: "HashiCorp Ember.js UI general guidelines - project context, build structure, and cross-cutting concerns"
|
||||
---
|
||||
|
||||
# HashiCorp Ember.js UI General Guidelines
|
||||
|
||||
This document provides general coding standards and project context for HashiCorp Ember.js UI applications. This serves as the central reference for project structure, framework information, and cross-cutting concerns.
|
||||
|
||||
> **Related Documents**: See domain-specific guidelines in `ember_javascript.instructions.md`, `ember_hbs.instructions.md`, `ember_styles.instructions.md`, and `ember_tests.instructions.md`.
|
||||
|
||||
## Project Context
|
||||
HashiCorp Ember.js UI applications provide web-based interfaces for HashiCorp's infrastructure tools and cloud platforms. These applications serve enterprise-grade interfaces used by DevOps teams, platform engineers, security professionals, and system administrators to manage infrastructure, security policies, and operational workflows.
|
||||
|
||||
Applications use modern Ember Octane patterns, Handlebars templates, and SCSS for styling with the HashiCorp Design System components.
|
||||
|
||||
## Repository Structure
|
||||
- `ui/app/components/` - Reusable UI components and their templates
|
||||
- `ui/app/models/` - Ember Data models representing API entities
|
||||
- `ui/app/routes/` - Route handlers for URL endpoints and data loading logic
|
||||
- `ui/app/templates/` - Page-level Handlebars templates
|
||||
- `ui/app/services/` - Ember services for shared functionality and state management
|
||||
- `ui/app/helpers/` - Template helper functions for data formatting and logic
|
||||
- `ui/tests/` - Integration, unit, and acceptance tests
|
||||
- `ui/app/styles/` - SCSS stylesheets and component-specific styles
|
||||
- `ui/config/` - Ember CLI configuration and environment settings
|
||||
- `ui/mirage/` - Mock server configuration for development and testing
|
||||
|
||||
## Framework and Tools
|
||||
- **Frontend Framework**: Ember.js 4.x with Ember Octane patterns and decorators
|
||||
- **Data Layer**: Ember Data for API communication with backend services
|
||||
- **Templating**: Handlebars templates with Ember's component architecture
|
||||
- **Styling**: SCSS with HashiCorp Design System (HDS) components and Bulma CSS framework
|
||||
- **Build System**: Ember CLI with Webpack for bundling and asset management
|
||||
- **Development**: ESLint for code linting, Prettier for code formatting
|
||||
|
||||
## File Naming Conventions
|
||||
- **Component Structure**: Components should have matching JavaScript/TypeScript and `.hbs` files in the same directory
|
||||
- **Directory Organization**: Organize new components in logical subdirectories by feature or domain
|
||||
|
||||
## Build and Deployment Structure
|
||||
- **Development Build**: `ember serve` creates development server with live reload
|
||||
- **Production Build**: `ember build --environment=production` generates optimized assets in `dist/`
|
||||
- **Asset Output**: Built files are typically served by the application's backend server or embedded in the main binary
|
||||
- **Integration**: UI is often compiled and integrated into the main application during release builds
|
||||
- **Testing**: `ember test` runs the full test suite with QUnit in headless Chrome
|
||||
|
||||
---
|
||||
|
||||
# Changelog Guidelines
|
||||
|
||||
For files in the `changelog/` directory:
|
||||
- **Enterprise features**: Use `ui (enterprise): descriptive text`
|
||||
- **Community features**: Use `ui: descriptive text`
|
||||
- Always indicate enterprise-only features in the description
|
||||
|
||||
```javascript
|
||||
// Changelog entries
|
||||
"ui (enterprise): Add advanced policy filtering" // enterprise features
|
||||
"ui: Fix configuration list pagination" // community features
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Dependency Management
|
||||
|
||||
## package.json Guidelines
|
||||
- Pin exact versions for critical dependencies or use tilde (`~`) for patch updates only
|
||||
- **WARNING**: Avoid caret (`^`) operator which allows minor version updates that may introduce breaking changes
|
||||
- Use tilde (`~`) for regular dependencies, exact versions for security-critical packages
|
||||
- Dependencies in `resolutions` block MUST be pinned (no `~` or `^`)
|
||||
- Keep `package.json` changes minimal and focused on the specific feature or fix
|
||||
- Always commit lock files (`yarn.lock`, `package-lock.json`) with dependency changes
|
||||
- Ensure package.json changes are independent of other code changes (except lock files)
|
||||
- **Reminder**: Consider coordinating dependency changes with backend teams when the UI is embedded in application binaries
|
||||
|
||||
Example dependency specification:
|
||||
```json
|
||||
{
|
||||
"dependencies": {
|
||||
"lodash": "4.17.21", // exact version for critical packages
|
||||
"express": "~4.18.0" // tilde for patch updates only
|
||||
},
|
||||
"resolutions": {
|
||||
"minimist": "1.2.6" // always exact for security fixes
|
||||
}
|
||||
}
|
||||
```
|
||||
113
.github/instructions/generic/ember_hbs.instructions.md
vendored
Normal file
113
.github/instructions/generic/ember_hbs.instructions.md
vendored
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
---
|
||||
applyTo: "vault/ui/**/*.hbs"
|
||||
description: "HashiCorp Ember.js UI Handlebars template coding standards"
|
||||
---
|
||||
|
||||
# HashiCorp Ember.js Handlebars Template Guidelines
|
||||
|
||||
This document provides Handlebars template coding standards for HashiCorp Ember.js UI applications.
|
||||
|
||||
> **Note**: For general project context, framework information, and repository structure, see `ember_general.instructions.md`.
|
||||
|
||||
## Template Best Practices
|
||||
- Check truthiness of arrays directly instead of using `.length` property
|
||||
- Use string interpolation `"prefix/{{value}}"` instead of `{{concat}}` helper
|
||||
- Remove unnecessary quotes around dynamic component arguments
|
||||
- Use `Hds::Link::Inline` for external documentation links instead of `<button>` elements
|
||||
- Make `selected` attributes dynamic rather than static values - warn if static values are used
|
||||
- Refactor conditionals to wrap content rather than entire elements when possible
|
||||
- Avoid inline `style` attributes and `{{style ...}}` helpers - define CSS classes in `.scss` files instead
|
||||
- Place `data-test-*` selectors as the last attribute on elements
|
||||
- Remove quotes around dynamic data attributes: `data-test-id={{value}}` not `data-test-id="{{value}}"`
|
||||
|
||||
Examples:
|
||||
```handlebars
|
||||
{{!-- Good: direct array check --}}
|
||||
{{#if this.model.allowed_roles}}
|
||||
|
||||
{{!-- Bad: unnecessary .length check --}}
|
||||
{{#if (gt this.model.allowed_roles.length 0)}}
|
||||
|
||||
{{!-- Good: string interpolation --}}
|
||||
@secret="role/{{@model.id}}"
|
||||
|
||||
{{!-- Bad: concat helper --}}
|
||||
@secret={{concat "role/" @model.id}}
|
||||
|
||||
{{!-- Good: conditional content, not element --}}
|
||||
<PH.Title>{{if this.version.isEnterprise "Enterprise" "Community"}} features</PH.Title>
|
||||
|
||||
{{!-- Bad: conditional wrapping entire element --}}
|
||||
{{#if this.version.isEnterprise}}
|
||||
<PH.Title>Enterprise features</PH.Title>
|
||||
{{else}}
|
||||
<PH.Title>Community features</PH.Title>
|
||||
{{/if}}
|
||||
|
||||
{{!-- Good: CSS classes instead of inline styles --}}
|
||||
<Hds::Button @text="Save" class="custom-button" data-test-save />
|
||||
|
||||
{{!-- Bad: inline style attribute --}}
|
||||
<Hds::Button @text="Save" style="margin-top: 10px;" data-test-save />
|
||||
|
||||
{{!-- Bad: style helper --}}
|
||||
<Hds::Button @text="Save" style={{style margin-top="10px"}} data-test-save />
|
||||
|
||||
{{!-- Good: data-test selector at the end --}}
|
||||
<Hds::Button @text="Save" @icon="loading" disabled={{this.isLoading}} data-test-save />
|
||||
|
||||
{{!-- Bad: data-test selector not at the end --}}
|
||||
<Hds::Button data-test-save @text="Save" @icon="loading" disabled={{this.isLoading}} />
|
||||
|
||||
{{!-- Good: no quotes around dynamic values --}}
|
||||
<div data-test-namespace-link={{option.label}}>
|
||||
|
||||
{{!-- Bad: unnecessary quotes --}}
|
||||
<div data-test-namespace-link="{{option.label}}">
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Content and Terminology
|
||||
|
||||
## Title and Heading Case Rules
|
||||
- **USE SENTENCE CASE**: All HTML headings (`<h1>`, `<h2>`, `<h3>`, etc.) should use sentence case (only first letter capitalized)
|
||||
- **NO TITLE CASE**: Avoid title case where every major word is capitalized
|
||||
- **Component arguments**: Use sentence case for `@title`, `@label`, and similar text properties
|
||||
- End descriptive text with proper punctuation
|
||||
- Follow proper grammar rules including ending sentences with periods
|
||||
- Use consistent terminology for product-specific features and components
|
||||
|
||||
Examples:
|
||||
```handlebars
|
||||
{{!-- CORRECT: Sentence case in HTML headings --}}
|
||||
<h2 class="title is-4">Quick actions</h2>
|
||||
<h3 class="title is-marginless is-6">Configuration settings</h3>
|
||||
<h1>Authentication methods</h1>
|
||||
|
||||
{{!-- INCORRECT: Title case in HTML headings --}}
|
||||
<h2 class="title is-4">Quick Actions</h2>
|
||||
<h3 class="title is-marginless is-6">Configuration Settings</h3>
|
||||
<h1>Authentication Methods</h1>
|
||||
```
|
||||
|
||||
```javascript
|
||||
// CORRECT: Sentence case in component arguments
|
||||
@title="Upload user's profile"
|
||||
@label="Configuration path"
|
||||
@placeholder="Enter mount path"
|
||||
|
||||
// INCORRECT: Title case or inconsistent casing
|
||||
@title="Upload User's Profile"
|
||||
@label="Configuration Path"
|
||||
@placeholder="Enter Mount Path"
|
||||
```
|
||||
|
||||
```handlebars
|
||||
{{!-- CORRECT: Sentence case in data-test attributes when they contain readable text --}}
|
||||
data-test-card-subtitle="configuration-settings"
|
||||
|
||||
{{!-- Component usage with proper casing --}}
|
||||
<Hds::Button @text="Create configuration" />
|
||||
<Hds::Alert @message="Operation completed successfully" />
|
||||
```
|
||||
100
.github/instructions/generic/ember_js.instructions.md
vendored
Normal file
100
.github/instructions/generic/ember_js.instructions.md
vendored
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
---
|
||||
applyTo: "vault/ui/**/*.{js,ts}"
|
||||
description: "HashiCorp Ember.js UI JavaScript and TypeScript coding standards"
|
||||
---
|
||||
|
||||
# HashiCorp Ember.js JavaScript & TypeScript Guidelines
|
||||
|
||||
This document provides JavaScript and TypeScript coding standards for HashiCorp Ember.js UI applications.
|
||||
|
||||
> **Note**: For general project context, framework information, and repository structure, see `ember_general.instructions.md`.
|
||||
|
||||
## Documentation Standards
|
||||
- Include JSDoc comments for all public functions, classes, and modules
|
||||
- Use `/** @module ModuleName */` for modules and `/** description */` for functions
|
||||
- Document function parameters, return types, and any side effects
|
||||
- Keep comments concise and focused on the "why" rather than the "what"
|
||||
- **Required**: Add documentation for all new files (components, helpers, services)
|
||||
|
||||
## Code Quality Standards
|
||||
- Remove all unused imports, variables, and functions before committing
|
||||
- Place comments directly above the code they describe, not inline or below
|
||||
- Update comments when code changes to maintain accuracy
|
||||
|
||||
## TypeScript Guidelines
|
||||
- **File Naming**: All new files should use `.ts` extension instead of `.js`
|
||||
- **Migration Strategy**: When modifying existing `.js` files, evaluate the effort required to convert to `.ts` and prioritize conversion if time permits
|
||||
- Use explicit types instead of `any` - prefer `unknown` for truly dynamic content
|
||||
- Define interfaces for object shapes and function signatures
|
||||
- Use type guards and discriminated unions for runtime type checking
|
||||
- Enable strict mode in TypeScript configuration
|
||||
|
||||
## Modern Ember Patterns
|
||||
- Replace `Route.extend`, `Model.extend`, or `Component.extend` with native JavaScript classes
|
||||
- Use Ember Octane conventions: tracked properties, decorators, and native class syntax
|
||||
- Create reusable components rather than one-off implementations
|
||||
- Co-locate component templates (`.hbs`) with their TypeScript files (`.ts` preferred over `.js`)
|
||||
- Prioritize reusability and maintainability when creating components - avoid overly complex or one-off implementations
|
||||
|
||||
## Asynchronous Programming
|
||||
- Use `async`/`await` with proper error handling in `try`/`catch` blocks
|
||||
- Only use `@task` from ember-concurrency when you need specific features like cancellation or `task.isRunning` state management
|
||||
- Avoid `setTimeout` in favor of `requestAnimationFrame` for UI updates or proper async patterns for delays
|
||||
- **Warning**: `setTimeout` is prone to testing issues and event loop management problems
|
||||
- Handle promise rejections explicitly rather than relying on global handlers
|
||||
|
||||
## Date and Time Handling
|
||||
- **WARNING**: Avoid `new Date()` as it uses the browser's timezone
|
||||
- Use `Date.UTC()` constructor instead of `new Date()` for consistent timezone handling
|
||||
- Use UTC methods like `getUTCFullYear()`, `getUTCMonth()` for date manipulation to ensure dates are calculated consistently
|
||||
- Consider using a date library like `date-fns` for complex date operations
|
||||
|
||||
## Error Handling and Logging
|
||||
- Use Ember's `assert` for runtime checks instead of `console.error`
|
||||
- Avoid `console.error` in production code - use proper logging libraries or framework-specific methods
|
||||
- Create meaningful error messages that include context about what failed
|
||||
- Use structured logging with consistent log levels (debug, info, warn, error)
|
||||
|
||||
---
|
||||
|
||||
# Component Development (JavaScript/TypeScript)
|
||||
|
||||
## Component Architecture
|
||||
- Use `@tracked` only for internal component state that changes over time
|
||||
- Never use `@tracked` on component arguments (properties passed from parent components)
|
||||
- Component class names must match their file names exactly
|
||||
- Place `.hbs` templates in the same directory as their `.ts` files (or `.js` for legacy files) within `ui/app/components/`
|
||||
- Organize new components in logical subdirectories by feature or domain
|
||||
|
||||
Examples:
|
||||
```javascript
|
||||
// Good: tracked for internal state
|
||||
@tracked isExpanded = false;
|
||||
|
||||
// Bad: tracked on argument
|
||||
@tracked @secret; // @secret is an argument, not internal state
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Model Definitions
|
||||
|
||||
## Ember Data Models
|
||||
- Use single-line syntax for `@attr` declarations with simple options
|
||||
- Avoid extra blank lines between consecutive single-line `@attr` declarations
|
||||
- Group related attributes together logically
|
||||
|
||||
Example:
|
||||
```javascript
|
||||
// Good: compact single-line format
|
||||
@attr('string', { label: 'Client ID' }) clientId;
|
||||
@attr('string', { label: 'Client Secret' }) clientSecret;
|
||||
@attr('boolean', { defaultValue: false }) isEnabled;
|
||||
|
||||
// Bad: unnecessary multi-line for simple attributes
|
||||
@attr('string', {
|
||||
label: 'Client ID',
|
||||
}) clientId;
|
||||
|
||||
@attr('string', { label: 'Client Secret' }) clientSecret;
|
||||
```
|
||||
36
.github/instructions/generic/ember_styles.instructions.md
vendored
Normal file
36
.github/instructions/generic/ember_styles.instructions.md
vendored
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
---
|
||||
applyTo: "vault/ui/**/*.scss"
|
||||
description: "HashiCorp Ember.js UI SCSS styling coding standards"
|
||||
---
|
||||
|
||||
# HashiCorp Ember.js SCSS Styling Guidelines
|
||||
|
||||
This document provides SCSS styling coding standards for HashiCorp Ember.js UI applications.
|
||||
|
||||
> **Note**: For general project context, framework information, and repository structure, see `ember_general.instructions.md`.
|
||||
|
||||
## CSS Best Practices
|
||||
- Avoid `z-index` - manage stacking order through DOM structure instead
|
||||
- Avoid `!important` - use more specific selectors for overrides
|
||||
|
||||
Examples:
|
||||
```scss
|
||||
// Good: specific selector for overrides
|
||||
.namespace-picker .button {
|
||||
color: red;
|
||||
}
|
||||
|
||||
// Bad: using !important
|
||||
.button {
|
||||
color: red !important;
|
||||
}
|
||||
|
||||
// Bad: using z-index for stacking
|
||||
.modal {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
// Good: manage stacking through DOM order in template
|
||||
// Place modal element after background overlay in template
|
||||
```
|
||||
225
.github/instructions/generic/ember_tests.instructions.md
vendored
Normal file
225
.github/instructions/generic/ember_tests.instructions.md
vendored
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
---
|
||||
applyTo: "vault/ui/tests/**/*.{js,ts}"
|
||||
description: "HashiCorp Ember.js testing standards and best practices"
|
||||
---
|
||||
|
||||
# HashiCorp Ember.js Testing Standards
|
||||
|
||||
This document provides testing standards and best practices for HashiCorp Ember.js UI applications.
|
||||
|
||||
> **Note**: For general project context, framework information, and repository structure, see `ember_general.instructions.md`.
|
||||
|
||||
## Testing Framework and Tools
|
||||
- **Testing Framework**: QUnit for unit, integration, and acceptance tests
|
||||
- **Mock Server**: Ember CLI Mirage for API mocking and test data
|
||||
- **Test Runners**: Ember CLI test runner with headless Chrome
|
||||
|
||||
## Test Directory Structure
|
||||
- `ui/tests/integration/` - Component integration tests
|
||||
- `ui/tests/unit/` - Service, helper, and model unit tests
|
||||
- `ui/tests/acceptance/` - End-to-end user workflow tests
|
||||
- `ui/mirage/` - Mock server configuration for development and testing
|
||||
- `ui/tests/helpers/` - Custom test helper functions and utilities
|
||||
|
||||
---
|
||||
|
||||
# Testing Standards
|
||||
|
||||
## Test Quality
|
||||
- Use `assert.true()` or `assert.false()` instead of `assert.ok()` for boolean checks
|
||||
- Provide descriptive assertion messages that explain what is being verified
|
||||
- Use `data-test-*` selectors for DOM interactions to decouple from styling
|
||||
- Place `this.server` setup at the top of test blocks when using ember-cli-mirage
|
||||
- Interact with elements directly rather than using Page Object patterns
|
||||
|
||||
Example test assertions:
|
||||
```javascript
|
||||
// Good: specific assertion with descriptive message
|
||||
assert.true(component.isVisible, 'Component should be visible after clicking toggle');
|
||||
|
||||
// Bad: vague assertion without context
|
||||
assert.ok(component.isVisible);
|
||||
```
|
||||
|
||||
## Asynchronous Testing
|
||||
- Use Ember's `run.later` instead of `setTimeout` in tests for better runloop control
|
||||
- Handle async operations with proper waiting patterns in tests
|
||||
- Ensure test isolation by resetting state between tests
|
||||
|
||||
## Mirage Server Setup
|
||||
- **Use `setupMirage(hooks)`** to automatically manage server lifecycle - no manual shutdown required
|
||||
- Place `this.server` setup at the top of test blocks when using ember-cli-mirage
|
||||
- Configure mock data that reflects realistic API responses
|
||||
- Use mirage factories for generating test data consistently
|
||||
- Reset server state between tests to ensure test isolation
|
||||
|
||||
**Recommended approach** - use `setupMirage()`:
|
||||
```javascript
|
||||
import { setupMirage } from 'ember-cli-mirage/test-support';
|
||||
|
||||
module('Integration | Component | my-component', function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
setupMirage(hooks); // Automatically handles server setup and shutdown
|
||||
|
||||
hooks.beforeEach(function () {
|
||||
this.server.create('model', { id: 1, name: 'Test Item' });
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
> **Note**: Avoid manual server setup and shutdown. Use `setupMirage(hooks)` instead to prevent memory leaks and reduce boilerplate code.
|
||||
|
||||
## DOM Testing Best Practices
|
||||
- Use `data-test-*` selectors for DOM interactions to decouple from styling
|
||||
- Test user interactions through realistic user flows
|
||||
- Verify state changes after user actions
|
||||
- Test error states and edge cases
|
||||
- Ensure accessibility features work correctly
|
||||
|
||||
Example DOM testing:
|
||||
```javascript
|
||||
// Good: using data-test selectors
|
||||
await click('[data-test-submit-button]');
|
||||
assert.true(find('[data-test-success-message]'), 'Success message should appear after submission');
|
||||
|
||||
// Bad: using CSS classes for testing
|
||||
await click('.btn-submit');
|
||||
assert.ok(find('.alert-success'));
|
||||
```
|
||||
|
||||
## Test Organization
|
||||
- **Use modules primarily for shared test setup and context**, not just organizational grouping
|
||||
- Nest modules only when tests benefit from the same `beforeEach` context or setup logic
|
||||
- Avoid excessive nesting that can make test structure confusing to navigate
|
||||
- Use descriptive test names that explain the scenario being tested
|
||||
- Include both positive and negative test cases
|
||||
- Test error handling and edge cases
|
||||
- Keep tests focused on a single behavior or outcome
|
||||
|
||||
**Good module usage** - shared setup benefits multiple tests:
|
||||
```javascript
|
||||
module('Integration | Component | secret-form', function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
setupMirage(hooks);
|
||||
|
||||
module('with authentication', function (hooks) {
|
||||
hooks.beforeEach(function () {
|
||||
// Shared setup that multiple tests need
|
||||
this.server.create('user', { authenticated: true });
|
||||
this.store = this.owner.lookup('service:store');
|
||||
this.currentUser = this.store.createRecord('user', { id: 1 });
|
||||
});
|
||||
|
||||
test('shows user-specific options when authenticated', function (assert) {
|
||||
// Test that benefits from the shared authentication setup
|
||||
});
|
||||
|
||||
test('allows advanced actions when authenticated', function (assert) {
|
||||
// Another test that needs the same authentication context
|
||||
});
|
||||
});
|
||||
|
||||
module('without authentication', function (hooks) {
|
||||
hooks.beforeEach(function () {
|
||||
// Different shared setup for unauthenticated state
|
||||
this.server.create('user', { authenticated: false });
|
||||
});
|
||||
|
||||
test('hides sensitive options when not authenticated', function (assert) {
|
||||
// Test that benefits from unauthenticated setup
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
**Avoid** - unnecessary nesting for organization only:
|
||||
```javascript
|
||||
// Don't do this - no shared setup benefit
|
||||
module('Integration | Component | secret-form', function (hooks) {
|
||||
module('input validation', function (hooks) {
|
||||
test('validates required fields', function (assert) { /* ... */ });
|
||||
test('validates field format', function (assert) { /* ... */ });
|
||||
});
|
||||
|
||||
module('form submission', function (hooks) {
|
||||
test('submits valid data', function (assert) { /* ... */ });
|
||||
test('handles submission errors', function (assert) { /* ... */ });
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
Example test structure:
|
||||
```javascript
|
||||
module('Integration | Component | secret-form', function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
test('it displays validation error when secret name is empty', async function (assert) {
|
||||
await render(hbs`<SecretForm @onSubmit={{this.handleSubmit}} />`);
|
||||
|
||||
await click('[data-test-submit-button]');
|
||||
|
||||
assert.true(
|
||||
find('[data-test-name-error]').textContent.includes('Secret name is required'),
|
||||
'Should display validation error for empty secret name'
|
||||
);
|
||||
});
|
||||
|
||||
test('it calls onSubmit with form data when valid', async function (assert) {
|
||||
let submittedData;
|
||||
this.handleSubmit = (data) => { submittedData = data; };
|
||||
|
||||
await render(hbs`<SecretForm @onSubmit={{this.handleSubmit}} />`);
|
||||
|
||||
await fillIn('[data-test-secret-name]', 'my-secret');
|
||||
await fillIn('[data-test-secret-value]', 'secret-value');
|
||||
await click('[data-test-submit-button]');
|
||||
|
||||
assert.deepEqual(submittedData, {
|
||||
name: 'my-secret',
|
||||
value: 'secret-value'
|
||||
}, 'Should submit form data with correct values');
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Debugging Tests
|
||||
|
||||
## Debugging Tips
|
||||
When debugging Ember templates in tests:
|
||||
- Use `{{debugger}}` inside templates to inspect values in the browser console
|
||||
- In the console during debugging:
|
||||
- Use `get('property.name')` to inspect nested properties
|
||||
- Use `context` to explore the current template context
|
||||
- Add console.log statements in test code to track execution flow
|
||||
- Use browser developer tools to inspect DOM state during test execution
|
||||
|
||||
Example debugging usage:
|
||||
```handlebars
|
||||
{{#each this.items as |item|}}
|
||||
{{debugger}}
|
||||
{{/each}}
|
||||
```
|
||||
|
||||
```javascript
|
||||
test('debugging example', async function (assert) {
|
||||
await render(hbs`<MyComponent @data={{this.testData}} />`);
|
||||
|
||||
// Pause execution to inspect DOM
|
||||
debugger;
|
||||
|
||||
console.log('Component state:', this.element.querySelector('[data-test-component]'));
|
||||
|
||||
await click('[data-test-button]');
|
||||
|
||||
// Inspect state after interaction
|
||||
debugger;
|
||||
});
|
||||
```
|
||||
|
||||
## Test Isolation
|
||||
- Reset component state between tests
|
||||
- Clear any global state or services
|
||||
- Ensure tests don't depend on execution order
|
||||
- Use hooks for setup and teardown consistently
|
||||
158
.github/instructions/generic/golang.instructions.md
vendored
Normal file
158
.github/instructions/generic/golang.instructions.md
vendored
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
---
|
||||
applyTo: "**/*.go"
|
||||
description: "Practical guidance for Golang programming"
|
||||
---
|
||||
|
||||
# Go Programming Instructions
|
||||
|
||||
## Code Style and Formatting
|
||||
- Use `gofmt` and `goimports` to format all Go code automatically
|
||||
- Follow standard Go naming conventions:
|
||||
- camelCase for unexported identifiers
|
||||
- PascalCase for exported identifiers
|
||||
- Use MixedCaps or mixedCaps rather than underscores for multiword names
|
||||
- Words in names that are initialisms or acronyms (e.g. “URL” or “NATO”) have a consistent case. For example, “URL” should appear as “URL” or “url” (as in “urlPony”, or “URLPony”), never as “Url”. As an example: ServeHTTP not ServeHttp. For identifiers with multiple initialized “words”, use for example “xmlHTTPRequest” or “XMLHTTPRequest”.
|
||||
- Keep line length reasonable (Go has no strict limit, but wrap long lines)
|
||||
- Use meaningful variable and function names
|
||||
|
||||
## Package Organization
|
||||
- Use lowercase, single-word package names, no hyphens or underscores
|
||||
- Keep packages focused and cohesive
|
||||
- Place main packages in `cmd/` directory for applications, unless the repository will only ever contain one executable, in which case a `main.go` at the root of the repository is ok
|
||||
- Package name should be the base name of its source directory
|
||||
|
||||
## Naming Conventions
|
||||
### Package Names
|
||||
- Use short, concise, evocative names
|
||||
- Prefer brevity since everyone using your package will type the name
|
||||
- Examples: `bufio.Reader` not `bufio.BufReader`, `ring.New` not `ring.NewRing`
|
||||
|
||||
### Interface Names
|
||||
- One-method interfaces use method name + "-er" suffix: `Reader`, `Writer`, `Formatter`
|
||||
- Honor canonical method signatures: `Read`, `Write`, `Close`, `String`
|
||||
|
||||
### Getters and Setters
|
||||
- Prefer exporting fields over adding getters and setters where possible
|
||||
- When required, don't use "Get" prefix for getters. For example, if the field name is `owner`, the getter should be `Owner()`, and the setter `SetOwner()`
|
||||
|
||||
## Functions and Methods
|
||||
- Use multiple return values to improve error handling
|
||||
- Only use named result parameters if multiple parameters are of the same type
|
||||
- Use defer for cleanup operations (closing files, unlocking mutexes)
|
||||
- Defer executes in LIFO order
|
||||
- Arguments to deferred functions are evaluated when defer executes
|
||||
|
||||
## Control Structures
|
||||
- Use initialization statement in if/switch when appropriate:
|
||||
```go
|
||||
if err := file.Chmod(0o664); err != nil {
|
||||
return err
|
||||
}
|
||||
```
|
||||
- Use switch statements instead of repeated if statements for validation:
|
||||
```go
|
||||
// Good:
|
||||
switch {
|
||||
case x < 0: return fmt.Errorf("negative value")
|
||||
case x > 10: return fmt.Errorf("value too large")
|
||||
}
|
||||
|
||||
// Bad:
|
||||
if x < 0 { return fmt.Errorf("negative value") }
|
||||
if x > 10 { return fmt.Errorf("value too large") }
|
||||
```
|
||||
- Omit unnecessary else statements when if ends with return/break/continue
|
||||
- Use type switches for interface type checking
|
||||
- Use range for iteration over arrays, slices, strings, maps, channels
|
||||
```go
|
||||
for i, v := range slice { /* ... */ } // Good
|
||||
for i := 0; i < len(slice); i++ { /* ... */ } // Bad
|
||||
```
|
||||
|
||||
## Error Handling and Design
|
||||
- Always handle errors explicitly
|
||||
- Use descriptive error messages that include context
|
||||
- Wrap errors with additional context when appropriate
|
||||
- Return errors as the last return value
|
||||
- Check error returns - they're provided for a reason
|
||||
- Use the "comma ok" idiom for optional error checking:
|
||||
```go
|
||||
if value, ok := someOperation(); !ok {
|
||||
// handle error case
|
||||
}
|
||||
```
|
||||
- Implement the error interface, `Is(error) bool` and `As(any) bool` for custom error types
|
||||
- Provide detailed error context including operation and file paths
|
||||
- Use panic only for truly exceptional cases or programming errors
|
||||
- Use recover to handle panics gracefully in server applications
|
||||
- Design errors to be useful when printed far from their origin
|
||||
|
||||
## Data Structures
|
||||
- Prefer zero-value-useful types in your designs
|
||||
- Prefer slices over arrays for most use cases
|
||||
- Understand slice sharing and capacity
|
||||
- Use `append()` built-in for growing slices
|
||||
- Use copy() for copying slice elements
|
||||
- Maps
|
||||
- Use "comma ok" idiom to test for presence: `value, ok := m[key]`
|
||||
- Use `delete(m, key)` to remove entries safely
|
||||
|
||||
## Interfaces and Composition
|
||||
- Design small, focused interfaces (often single-method)
|
||||
- Accept interfaces, return concrete types
|
||||
- Use empty interface `interface{}` or `any` sparingly
|
||||
- Prefer composition over large interfaces
|
||||
- Use type assertions and type switches for interface conversions
|
||||
- Embed types to promote methods and satisfy interfaces
|
||||
- Use embedding for has-a relationships, not is-a
|
||||
- Understand method promotion and shadowing rules
|
||||
|
||||
## Concurrency
|
||||
- Don't communicate by sharing memory; share memory by communicating
|
||||
- Use channels for goroutine communication and synchronization
|
||||
- Use goroutines for concurrent execution: `go functionCall()`
|
||||
- Use buffered channels as semaphores for limiting concurrency
|
||||
- Use select for non-blocking channel operations
|
||||
- Prefer structured concurrency patterns over ad-hoc goroutine creation
|
||||
- Unbuffered channels provide synchronization
|
||||
- Buffered channels can improve performance and provide semaphore behavior
|
||||
- Close channels to signal completion to range loops
|
||||
|
||||
## Documentation
|
||||
- Write clear godoc comments for exported functions and types
|
||||
- Start comments with the name of the item being documented
|
||||
- Use complete sentences in documentation
|
||||
- Provide examples in documentation when helpful
|
||||
- Document any unusual behavior or requirements
|
||||
|
||||
## Best Practices
|
||||
- Keep functions small and focused
|
||||
- Use context for cancellation and timeouts
|
||||
- Avoid global variables when possible
|
||||
- Use the blank identifier `_` to discard unused values
|
||||
- Make zero values useful in your type designs
|
||||
- Use init() functions for package initialization
|
||||
- Initialize complex data with composite literals
|
||||
- Profile before optimizing
|
||||
- Use build constraints for platform-specific code
|
||||
- Understand escape analysis and stack vs heap allocation
|
||||
- Use sync.Pool for frequently allocated objects
|
||||
|
||||
## Common Idioms
|
||||
- Use `fmt.Stringer` interface for custom string representations
|
||||
- Implement `io.Reader` and `io.Writer` interfaces when appropriate
|
||||
- Use functional options pattern for configuration
|
||||
- Use builder pattern for complex object construction
|
||||
- Prefer early returns to reduce nesting
|
||||
- Initialize complex data with composite literals
|
||||
|
||||
### Type Embedding
|
||||
- Embed types to promote methods and satisfy interfaces
|
||||
- Use embedding for has-a relationships, not is-a
|
||||
- Understand method promotion and shadowing rules
|
||||
|
||||
### Performance
|
||||
- Understand escape analysis and stack vs heap allocation
|
||||
- Use sync.Pool for frequently allocated objects
|
||||
- Profile before optimizing
|
||||
- Use build constraints for platform-specific code
|
||||
29
.github/instructions/generic/golang_tests.instructions.md
vendored
Normal file
29
.github/instructions/generic/golang_tests.instructions.md
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
applyTo: "**/*_test.go"
|
||||
description: "Practical guidance for writing tests in Go"
|
||||
---
|
||||
|
||||
# Golang Testing Guidelines
|
||||
*Practical guidance for writing tests in Go*
|
||||
|
||||
## General Guidelines
|
||||
- Write unit tests for all public functions
|
||||
- Use table-driven tests when appropriate
|
||||
- Follow naming convention: `Test_FunctionName`
|
||||
- Use `t.Parallel()` for faster test execution and to encourage writing tests that don't share state
|
||||
|
||||
## Tools
|
||||
- Use testify/assert and testify/require for consistent assertions
|
||||
|
||||
## Test Structure
|
||||
- Use t.Helper() to mark helper functions
|
||||
- Use subtests for organizing related test cases with t.Run()
|
||||
|
||||
## Integration Tests
|
||||
- Use testcontainers to spin up dependencies like postgres or redis
|
||||
|
||||
## Black box testing
|
||||
- The test should be in feature_test package to be the first client of the feature package
|
||||
|
||||
## End-to-End Testing (Future Enhancement)
|
||||
<!-- TODO: Add guidance for end-to-end testing with enos and cloud-first testing in Vault Cloud -->
|
||||
45
.github/instructions/generic/testing.instructions.md
vendored
Normal file
45
.github/instructions/generic/testing.instructions.md
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
---
|
||||
applyTo: "**/*_test.go,**/*_spec.rb"
|
||||
description: "Practical guidance for writing tests across languages"
|
||||
---
|
||||
|
||||
# Philosophy & Principles
|
||||
|
||||
## Testing:
|
||||
- Test coverage is not a metric to optimize for
|
||||
- Test behavior and not implementation detail
|
||||
- Write tests that are robust to refactoring the code under test
|
||||
|
||||
### Value of a test
|
||||
- Test is code that needs to be maintained
|
||||
- If a test is not valuable, delete it
|
||||
|
||||
### Tests are documentation
|
||||
- Use the given-when-then pattern to communicate each test case
|
||||
- Test names should express intent
|
||||
|
||||
## Test Design & Quality
|
||||
*How to design reliable, maintainable tests*
|
||||
|
||||
### Test Isolation
|
||||
- A unit test should only fail for one reason
|
||||
- Do not share state between tests
|
||||
- Cleanup resources after the test
|
||||
- If files are needed, use a temp directory (in Go, prefer `t.TempDir()` for automatic cleanup)
|
||||
|
||||
### Test Stability
|
||||
- Do not use sleeping in a test
|
||||
|
||||
### Test Structure
|
||||
- Consider parametrized tests where it makes sense
|
||||
|
||||
### Mocks
|
||||
- Preferably do not use mocks
|
||||
- If you use mocks, assert the mock expectations
|
||||
|
||||
## Supporting Code Quality
|
||||
*Making the code under test more testable*
|
||||
|
||||
### Code under test
|
||||
- If the code relies on magic numbers or constants: Extract them
|
||||
- Consider introducing interfaces
|
||||
16
.github/instructions/index.md
vendored
Normal file
16
.github/instructions/index.md
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# Instructions
|
||||
|
||||
## Generic
|
||||
The generic folder contains instructions that can simply be copied into your teams repo for reuse. They are generic problem solving rules.
|
||||
|
||||
- golang_test.instructions.md
|
||||
Best practice for writing tests in Golang
|
||||
|
||||
## Specific
|
||||
The specific folder contains instructions that are not intended for reuse.
|
||||
|
||||
config.instructions.md
|
||||
Guidance for the pkg/config package in the terraform-enterprise repository, providing additional context, such as the requirement to consider backwards compatability.
|
||||
|
||||
style.instructions.md
|
||||
Guidance for writing documentation. Used in the web-unified-docs-internal repo.
|
||||
Loading…
Reference in a new issue