Migrate from ember-cli-mirage to miragejs (#3088)
* chore: 🤖 import explicit mirage references * chore: 🤖 add mirage setupMirage helper * chore: 🤖 working example with application adapter test * chore: 🤖 use internal setupMirage test helper from api addon * chore: 🤖 conditionally load mirage * chore: 🤖 filter mirage folder inclusion in production builds * chore: 🤖 drop ember-mirage and use our own test helpers * chore: 🤖 collapse reference to import declaration * docs: ✏️ add comment better explaining the mirage test env * chore: 🤖 update configuration and manage mirage-related deps * fix: 🐛 restore ipc mock and add missing checkOS handler * chore: 🤖 add comment explaining omitting mirage deps in build * chore: 🤖 allow mirage.enabled to include deps and handlers * chore: 🤖 re-enable mirage for core dummy app * Add missing copyright headers * chore: 🤖 use embroider macros to conditionally start mirage * docs: ✏️ update api readme for mirage changes * chore: 🤖 replace remaining ember-cli-mirage references * chore: 🤖 add mirage to test builds * fix: 🐛 ensure that auto mirage start doesn't happen in test env * chore: 🤖 use const instead of var Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com> * refactor: 💡 use cleaner logic for excluded api build modules * fix: 🐛 handle issue where importSync was too eager This was fixed by bumping the @embroider/macros dependency that includes a fix to this issue: https://github.com/embroider-build/embroider/pull/2511 * refactor: 💡 move mirage from addon to app directory * refactor: 💡 update mirage test helper to be a factory * chore: 🤖 exclude mirage directory when necessary at build time * chore: 🤖 add miragejs as admin dev dependency * refactor: 💡 update reference to startMirage * chore: 🤖 update local mirage test helper * chore: 🤖 change import path for mirage on desktop * chore: 🤖 update imports in tests for startMirage * chore: 🤖 update startMirage imports for api addon tests * chore: 🤖 add miragejs dev dep to desktop * docs: ✏️ update README * chore: 🤖 set up setupMirage for core tests * chore: 🤖 fix copyright header * Add missing copyright headers --------- Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com>
This commit is contained in:
1 parent
72fa6d86c4
commit
63b810d53f
191 files changed
+497
-212
No files matched your search
+37
-4
@@ -23,15 +23,48 @@ This addon contains the API data access layer for Boundary.
|
||||
Add this addon to an Ember application's `devDependencies` as:
|
||||
`"api": "workspace:*"`, for applications included in this monorepo.
|
||||
|
||||
Since this addon also includes Mirage mocks, be sure to install
|
||||
`ember-cli-mirage` and add the following config to your UI project:
|
||||
This addon also includes Mirage mocks. To include the `miragejs` dependency and this addon's mirage handlers configure the consuming app's `config/environment.js`
|
||||
|
||||
```js
|
||||
'ember-cli-mirage': {
|
||||
directory: '../../addons/api/mirage'
|
||||
mirage: {
|
||||
enabled: true
|
||||
}
|
||||
```
|
||||
|
||||
Include `miragejs` and any api addon `peerDependencies` used by the mirage as dev dependencies in the consuming app,
|
||||
eg: `@faker-js/faker`, otherwise mirage handler code might fail with an error.
|
||||
|
||||
To have mirage start and intercept requests when the application starts:
|
||||
1. Add the `@embroider/macros` dependency to your application
|
||||
2. Configure `@embroider/macros` with `startMirageWithApp` based on app's config within `ember-cli-build.js`:
|
||||
|
||||
```js
|
||||
// ember-cli-build.js
|
||||
module.exports = async function (defaults) {
|
||||
// load the app's config
|
||||
const { EMBER_ENV } = process.env;
|
||||
var config = require('./config/environment')(EMBER_ENV);
|
||||
|
||||
const app = new EmberApp(defaults, {
|
||||
'@embroider/macros': {
|
||||
setOwnConfig: {
|
||||
startMirageWithApp: config.mirage?.enabled ?? false
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
3. Finally, use the `@embroider/macros` config value for `startMirageWithApp` in `app/app.js` to conditionally start mirage:
|
||||
|
||||
```js
|
||||
import { macroCondition, importSync, getOwnConfig, isTesting } from '@embroider/macros';
|
||||
|
||||
if (macroCondition(getOwnConfig().startMirageWithApp && !isTesting())) {
|
||||
const startServer = importSync('[name of host app]/mirage/config').default;
|
||||
startServer({});
|
||||
}
|
||||
```
|
||||
## Installation
|
||||
|
||||
See monorepo README for installation instructions.
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright IBM Corp. 2021, 2026
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import { settled } from '@ember/test-helpers';
|
||||
|
||||
export function createSetupMirage(startMirage) {
|
||||
return function setupMirage(hooks) {
|
||||
hooks.beforeEach(function () {
|
||||
if (!this.owner) {
|
||||
throw new Error(
|
||||
'Must call one of the ember-qunit setupTest() / setupRenderingTest() / setupApplicationTest() first',
|
||||
);
|
||||
}
|
||||
|
||||
// the environment property here is configuration to the mirage server:
|
||||
// https://github.com/miragejs/miragejs/blob/7ff4f3f6fe56bf0cb1648f5af3f5210fcb07e20b/types/index.d.ts#L383
|
||||
// It is not related to ember's build environment. In this case for mirage the "test" environment does
|
||||
// not load the default scenario:
|
||||
// https://github.com/miragejs/miragejs/blob/7ff4f3f6fe56bf0cb1648f5af3f5210fcb07e20b/lib/server.js#L302
|
||||
this.server = startMirage({ environment: 'test' });
|
||||
});
|
||||
|
||||
hooks.afterEach(function () {
|
||||
return settled().then(() => {
|
||||
if (this.server) {
|
||||
this.server.shutdown();
|
||||
delete this.server;
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -3,12 +3,7 @@
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import {
|
||||
discoverEmberDataModels,
|
||||
applyEmberDataSerializers,
|
||||
} from 'ember-cli-mirage';
|
||||
import { createServer, Response } from 'miragejs';
|
||||
import environmentConfig from '../config/environment';
|
||||
import { authHandler, deauthHandler } from './route-handlers/auth';
|
||||
import { targetHandler } from './route-handlers/target';
|
||||
import { pickRandomStatusString } from './factories/session';
|
||||
@@ -17,19 +12,177 @@ import makeBooleanFilter from './helpers/bexpr-filter';
|
||||
import { faker } from '@faker-js/faker';
|
||||
import { asciicasts } from './data/asciicasts';
|
||||
import { TYPE_WORKER_PKI } from 'api/models/worker';
|
||||
import environmentConfig from 'ember-get-config';
|
||||
|
||||
// mirage models (alphabetical)
|
||||
import accountModel from './models/account';
|
||||
import aliasModel from './models/alias';
|
||||
import authMethodModel from './models/auth-method';
|
||||
import baseModel from './models/base';
|
||||
import channelRecordingModel from './models/channel-recording';
|
||||
import connectionRecordingModel from './models/connection-recording';
|
||||
import credentialLibraryModel from './models/credential-library';
|
||||
import credentialStoreModel from './models/credential-store';
|
||||
import credentialModel from './models/credential';
|
||||
import groupModel from './models/group';
|
||||
import hostCatalogModel from './models/host-catalog';
|
||||
import hostSetModel from './models/host-set';
|
||||
import hostModel from './models/host';
|
||||
import managedGroupModel from './models/managed-group';
|
||||
import policyModel from './models/policy';
|
||||
import roleModel from './models/role';
|
||||
import scopeModel from './models/scope';
|
||||
import sessionRecordingModel from './models/session-recording';
|
||||
import sessionModel from './models/session';
|
||||
import storageBucketModel from './models/storage-bucket';
|
||||
import targetModel from './models/target';
|
||||
import userModel from './models/user';
|
||||
import workerModel from './models/worker';
|
||||
|
||||
// mirage serializers (alphabetical)
|
||||
import accountSerializer from './serializers/account';
|
||||
import aliasSerializer from './serializers/alias';
|
||||
import applicationSerializer from './serializers/application';
|
||||
import authMethodSerializer from './serializers/auth-method';
|
||||
import channelRecordingSerializer from './serializers/channel-recording';
|
||||
import connectionRecordingSerializer from './serializers/connection-recording';
|
||||
import credentialLibrarySerializer from './serializers/credential-library';
|
||||
import credentialStoreSerializer from './serializers/credential-store';
|
||||
import credentialSerializer from './serializers/credential';
|
||||
import groupSerializer from './serializers/group';
|
||||
import hostCatalogSerializer from './serializers/host-catalog';
|
||||
import hostSetSerializer from './serializers/host-set';
|
||||
import hostSerializer from './serializers/host';
|
||||
import managedGroupSerializer from './serializers/managed-group';
|
||||
import policySerializer from './serializers/policy';
|
||||
import roleSerializer from './serializers/role';
|
||||
import scopeSerializer from './serializers/scope';
|
||||
import sessionRecordingSerializer from './serializers/session-recording';
|
||||
import sessionSerializer from './serializers/session';
|
||||
import storageBucketSerializer from './serializers/storage-bucket';
|
||||
import targetSerializer from './serializers/target';
|
||||
import userSerializer from './serializers/user';
|
||||
import workerSerializer from './serializers/worker';
|
||||
|
||||
// mirage scenarios (alphabetical)
|
||||
import defaultScenario from './scenarios/default';
|
||||
import ipcScenario from './scenarios/ipc';
|
||||
|
||||
// mirage factories (alphabetical)
|
||||
import accountFactory from './factories/account';
|
||||
import aliasFactory from './factories/alias';
|
||||
import authMethodFactory from './factories/auth-method';
|
||||
import channelRecordingFactory from './factories/channel-recording';
|
||||
import connectionRecordingFactory from './factories/connection-recording';
|
||||
import credentialLibraryFactory from './factories/credential-library';
|
||||
import credentialStoreFactory from './factories/credential-store';
|
||||
import credentialFactory from './factories/credential';
|
||||
import groupFactory from './factories/group';
|
||||
import hostCatalogFactory from './factories/host-catalog';
|
||||
import hostSetFactory from './factories/host-set';
|
||||
import hostFactory from './factories/host';
|
||||
import managedGroupFactory from './factories/managed-group';
|
||||
import policyFactory from './factories/policy';
|
||||
import roleFactory from './factories/role';
|
||||
import scopeFactory from './factories/scope';
|
||||
import sessionRecordingFactory from './factories/session-recording';
|
||||
import storageBucketFactory from './factories/storage-bucket';
|
||||
import sessionFactory from './factories/session';
|
||||
import targetFactory from './factories/target';
|
||||
import userFactory from './factories/user';
|
||||
import workerFactory from './factories/worker';
|
||||
|
||||
const isTesting = environmentConfig.environment === 'test';
|
||||
|
||||
// Main function
|
||||
// More info about server configuration https://www.ember-cli-mirage.com/docs/advanced/server-configuration
|
||||
// More info about server configuration:
|
||||
// https://github.com/miragejs/miragejs/blob/7ff4f3f6fe56bf0cb1648f5af3f5210fcb07e20b/types/index.d.ts#L375-L404
|
||||
export default function (mirageConfig) {
|
||||
let finalConfig = {
|
||||
...mirageConfig,
|
||||
models: {
|
||||
...discoverEmberDataModels(mirageConfig.store),
|
||||
...mirageConfig.models,
|
||||
|
||||
scenarios: {
|
||||
default: defaultScenario,
|
||||
ipcScenario: ipcScenario,
|
||||
},
|
||||
serializers: applyEmberDataSerializers(mirageConfig.serializers),
|
||||
|
||||
factories: {
|
||||
account: accountFactory,
|
||||
alias: aliasFactory,
|
||||
authMethod: authMethodFactory,
|
||||
channelRecording: channelRecordingFactory,
|
||||
connectionRecording: connectionRecordingFactory,
|
||||
credentialLibrary: credentialLibraryFactory,
|
||||
credentialStore: credentialStoreFactory,
|
||||
credential: credentialFactory,
|
||||
group: groupFactory,
|
||||
hostCatalog: hostCatalogFactory,
|
||||
hostSet: hostSetFactory,
|
||||
host: hostFactory,
|
||||
managedGroup: managedGroupFactory,
|
||||
policy: policyFactory,
|
||||
role: roleFactory,
|
||||
scope: scopeFactory,
|
||||
sessionRecording: sessionRecordingFactory,
|
||||
session: sessionFactory,
|
||||
storageBucket: storageBucketFactory,
|
||||
target: targetFactory,
|
||||
user: userFactory,
|
||||
worker: workerFactory,
|
||||
},
|
||||
|
||||
models: {
|
||||
account: accountModel,
|
||||
alias: aliasModel,
|
||||
authMethod: authMethodModel,
|
||||
base: baseModel,
|
||||
channelRecording: channelRecordingModel,
|
||||
connectionRecording: connectionRecordingModel,
|
||||
credentialLibrary: credentialLibraryModel,
|
||||
credentialStore: credentialStoreModel,
|
||||
credential: credentialModel,
|
||||
group: groupModel,
|
||||
hostCatalog: hostCatalogModel,
|
||||
hostSet: hostSetModel,
|
||||
host: hostModel,
|
||||
managedGroup: managedGroupModel,
|
||||
policy: policyModel,
|
||||
role: roleModel,
|
||||
scope: scopeModel,
|
||||
sessionRecording: sessionRecordingModel,
|
||||
session: sessionModel,
|
||||
storageBucket: storageBucketModel,
|
||||
target: targetModel,
|
||||
user: userModel,
|
||||
worker: workerModel,
|
||||
},
|
||||
|
||||
serializers: {
|
||||
account: accountSerializer,
|
||||
alias: aliasSerializer,
|
||||
application: applicationSerializer,
|
||||
authMethod: authMethodSerializer,
|
||||
channelRecording: channelRecordingSerializer,
|
||||
connectionRecording: connectionRecordingSerializer,
|
||||
credentialLibrary: credentialLibrarySerializer,
|
||||
credentialStore: credentialStoreSerializer,
|
||||
credential: credentialSerializer,
|
||||
group: groupSerializer,
|
||||
hostCatalog: hostCatalogSerializer,
|
||||
hostSet: hostSetSerializer,
|
||||
host: hostSerializer,
|
||||
managedGroup: managedGroupSerializer,
|
||||
policy: policySerializer,
|
||||
role: roleSerializer,
|
||||
scope: scopeSerializer,
|
||||
sessionRecording: sessionRecordingSerializer,
|
||||
session: sessionSerializer,
|
||||
storageBucket: storageBucketSerializer,
|
||||
target: targetSerializer,
|
||||
user: userSerializer,
|
||||
worker: workerSerializer,
|
||||
},
|
||||
|
||||
routes,
|
||||
};
|
||||
return createServer(finalConfig);
|
||||
@@ -58,7 +211,7 @@ function routes() {
|
||||
});
|
||||
|
||||
// make this `/api`, for example, if your API is namespaced
|
||||
this.namespace = environmentConfig.api.namespace;
|
||||
this.namespace = environmentConfig.api?.namespace;
|
||||
// delay for each request, automatically set to 0 during testing
|
||||
this.timing = 1;
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -22,6 +22,14 @@ export default function initializeMockIPC(server, config) {
|
||||
|
||||
clusterUrl = null;
|
||||
|
||||
checkOS() {
|
||||
return {
|
||||
isLinux: false,
|
||||
isMac: true,
|
||||
isWindows: false,
|
||||
};
|
||||
}
|
||||
|
||||
getClusterUrl() {
|
||||
return this.clusterUrl;
|
||||
}
|
||||
@@ -273,7 +281,7 @@ export default function initializeMockIPC(server, config) {
|
||||
* We mock certain functions even in electron (e.g. hasMacOSChrome) when running
|
||||
* locally which will force a certain appearance regardless of platform
|
||||
*/
|
||||
if (config['ember-cli-mirage'].enabled && !isTesting) {
|
||||
if (config.mirage?.enabled && !isTesting) {
|
||||
const mockIPC = new MockIPC();
|
||||
|
||||
window.addEventListener('message', async function (event) {
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loaded 100 of 191 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user