From 028c96b7f93f0ca27f19a24c77d2a66660e9613e Mon Sep 17 00:00:00 2001 From: tintinthong Date: Tue, 24 Mar 2026 15:38:29 +0800 Subject: [PATCH] try to run live test from ci --- .github/workflows/ci-test.yaml | 103 +++++++++++++++++++++++ sample-command-card.gts | 144 +++++++++++++++++++++++++++++++++ 2 files changed, 247 insertions(+) create mode 100644 sample-command-card.gts diff --git a/.github/workflows/ci-test.yaml b/.github/workflows/ci-test.yaml index f7f3ef6..440346b 100644 --- a/.github/workflows/ci-test.yaml +++ b/.github/workflows/ci-test.yaml @@ -131,3 +131,106 @@ jobs: - name: Print realm server logs if: always() run: cat /tmp/server.log + + live-test: + name: Live Tests (realm) + runs-on: ubuntu-latest + concurrency: + group: live-test-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + steps: + # Checkout the boxel monorepo at is-live-test branch (has testem-live.js + test:live) + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 + with: + repository: cardstack/boxel + ref: is-live-test + + # Checkout this catalog repo into a temp location + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 + with: + path: boxel-catalog-src + + # Copy catalog files into the monorepo + - name: Copy catalog files into monorepo + run: | + cd packages/catalog-realm + find . -mindepth 1 \ + ! -name '.gitignore' \ + ! -name 'tsconfig.json' \ + ! -name 'package.json' \ + ! -name '.realm.json' \ + ! -path './Spec' \ + ! -path './Spec/*' \ + ! -path './fields' \ + ! -path './fields/*' \ + ! -path './components' \ + ! -path './components/*' \ + ! -path './commands' \ + ! -path './commands/suggest-avatar.gts' \ + ! -path './utils' \ + ! -path './utils/*' \ + ! -path './resources' \ + ! -path './resources/*' \ + ! -path './catalog-app' \ + ! -path './catalog-app/*' \ + ! -name '.' \ + -exec rm -rf {} + 2>/dev/null || true + cd ../.. + rsync -av --exclude='tsconfig.json' --exclude='package.json' --exclude='.realm.json' --exclude='.gitignore' --exclude='tests/' boxel-catalog-src/ packages/catalog-realm/ + + - uses: ./.github/actions/init + + - name: Build common dependencies + run: pnpm run build-common-deps + + - name: Build Host for tests + run: NODE_OPTIONS='--max-old-space-size=8192' pnpm build + working-directory: packages/host + + - name: Serve boxel-icons + run: pnpm serve &> /tmp/icon-server.log & + working-directory: packages/boxel-icons + + - name: Disable TCP/UDP network offloading + run: sudo ethtool -K eth0 tx off rx off + + - name: Serve host dist for realm server + uses: JarvusInnovations/background-action@2428e7b970a846423095c79d43f759abf979a635 # 1.0.7 + with: + run: pnpm serve:dist & + working-directory: packages/host + wait-for: 3m + wait-on: http-get://localhost:4200 + + - name: Start realm servers + run: pnpm start:services-for-host-tests | tee -a /tmp/server.log & + working-directory: packages/realm-server + + - name: Create realm users + run: pnpm register-realm-users + working-directory: packages/matrix + + - name: Install D-Bus helpers + run: | + sudo apt-get update + sudo apt-get install -y dbus-x11 upower + sudo service dbus restart + sudo service upower restart + + - name: Live test suite + run: dbus-run-session -- pnpm test:live + working-directory: packages/host + env: + DBUS_SYSTEM_BUS_ADDRESS: unix:path=/run/dbus/system_bus_socket + + - name: Upload junit report + uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # 4.6.1 + if: ${{ !cancelled() }} + with: + name: host-live-test-report + path: junit/host-live.xml + retention-days: 30 + + - name: Print realm server logs + if: ${{ !cancelled() }} + run: cat /tmp/server.log diff --git a/sample-command-card.gts b/sample-command-card.gts new file mode 100644 index 0000000..11d115a --- /dev/null +++ b/sample-command-card.gts @@ -0,0 +1,144 @@ +import { + CardDef, + field, + contains, + Component, +} from 'https://cardstack.com/base/card-api'; +import StringField from 'https://cardstack.com/base/string'; + +export class SampleCommandCard extends CardDef { + static displayName = 'Sample Command Card'; + @field title = contains(StringField); + + static isolated = class Isolated extends Component { + + }; +} + +// ── Tests (imports resolved via loader.shimModule in live-test.js) ──────────── +import { on } from '@ember/modifier'; +import { service } from '@ember/service'; +import { click, render, waitUntil } from '@ember/test-helpers'; +import GlimmerComponent from '@glimmer/component'; +import { module, test } from 'qunit'; + +import { type Store } from '@cardstack/runtime-common'; +import { + setupCardTest, + setupIntegrationTestRealm, + testRealmURL, + withCachedRealmSetup, + type TestContextWithSave, +} from '@cardstack/host/tests/helpers'; +import { TestRealmAdapter } from '@cardstack/host/tests/helpers/adapter'; + +class CreateCardButton extends GlimmerComponent { + @service declare store: Store; + + createCard = async () => { + await this.store.add( + new SampleCommandCard({ title: 'Hello from live-test' }), + ); + }; + + +} + +export function runTests() { + module('Catalog | SampleCommandCard', function (hooks) { + let { mockMatrixUtils } = setupCardTest(hooks); + + let testRealmAdapter: TestRealmAdapter; + let testRealm: Awaited>['realm']; + + hooks.beforeEach(async function () { + let result = await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: { + 'sample-command-card.gts': { SampleCommandCard }, + '.realm.json': '{ "name": "Sample Realm" }', + }, + }), + ); + testRealmAdapter = result.adapter; + testRealm = result.realm; + }); + + test('clicking Create Card writes a new card to the realm', async function (this: TestContextWithSave, assert) { + assert.expect(3); + + let savedUrl: URL | undefined; + this.onSave((url, doc) => { + savedUrl = url; + assert.strictEqual( + (doc as any).data.attributes.title, + 'Hello from live-test', + 'saved doc has correct title', + ); + }); + + await render(); + await click('button'); + + assert.ok(savedUrl, 'card was saved to realm'); + let relativePath = `${savedUrl!.href.substring(testRealmURL.length)}.json`; + let file = await testRealmAdapter.openFile(relativePath); + assert.ok(file, 'card JSON file exists in the realm adapter'); + }); + + test('search finds the newly created card', async function (this: TestContextWithSave, assert) { + assert.expect(3); + + let savedUrl: URL | undefined; + this.onSave((url) => { + savedUrl = url; + }); + + await render(); + await click('button'); + + await waitUntil(() => Boolean(savedUrl), { timeout: 5000 }); + + await waitUntil( + async () => { + let { data: cards } = + await testRealm.realmIndexQueryEngine.searchCards({ + filter: { + on: { + module: `${testRealmURL}sample-command-card`, + name: 'SampleCommandCard', + }, + eq: { title: 'Hello from live-test' }, + }, + }); + return cards.length === 1; + }, + { timeout: 5000 }, + ); + + let { data: cards } = await testRealm.realmIndexQueryEngine.searchCards({ + filter: { + on: { + module: `${testRealmURL}sample-command-card`, + name: 'SampleCommandCard', + }, + eq: { title: 'Hello from live-test' }, + }, + }); + + assert.strictEqual(cards.length, 1, 'search returns the created card'); + assert.strictEqual( + (cards[0] as any).attributes?.title, + 'Hello from live-test', + 'search result has correct title', + ); + assert.ok(savedUrl, 'card save completed'); + }); + }); +}