diff --git a/.github/workflows/code-linting.yaml b/.github/workflows/code-linting.yaml deleted file mode 100644 index 3a501da7..00000000 --- a/.github/workflows/code-linting.yaml +++ /dev/null @@ -1,28 +0,0 @@ -name: CI -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -jobs: - lint-code: - strategy: - matrix: - os: [macos-latest, ubuntu-latest, windows-latest] - runs-on: ${{ matrix.os }} - steps: - - name: Checkout - uses: actions/checkout@v4 - - uses: pnpm/action-setup@v4 - - name: Install Node.js - uses: actions/setup-node@v4.1.0 - with: - node-version: 20.x - cache: 'pnpm' - - name: Install Dependencies - run: npx npm-run-all -l verify-deps:* - - name: Lint Code - run: pnpm run lint - - name: Test Typings - run: pnpm run test:typings diff --git a/.github/workflows/commit-linting.yaml b/.github/workflows/commit-linting.yaml deleted file mode 100644 index ffcb55ef..00000000 --- a/.github/workflows/commit-linting.yaml +++ /dev/null @@ -1,13 +0,0 @@ -name: CI -on: - pull_request: - branches: [ main ] - -jobs: - lint-commit-messages: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - uses: wagoid/commitlint-github-action@v5 diff --git a/.github/workflows/e2e-testing.yaml b/.github/workflows/e2e-testing.yaml index 59d711f2..719d36a4 100644 --- a/.github/workflows/e2e-testing.yaml +++ b/.github/workflows/e2e-testing.yaml @@ -8,8 +8,10 @@ on: jobs: test-e2e: strategy: + fail-fast: false matrix: os: [macos-latest, ubuntu-latest] + # os: [macos-latest] runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/pr-linting.yaml b/.github/workflows/pr-linting.yaml deleted file mode 100644 index 3b621d52..00000000 --- a/.github/workflows/pr-linting.yaml +++ /dev/null @@ -1,13 +0,0 @@ -name: CI -on: - pull_request: - types: ['opened', 'edited', 'reopened', 'synchronize'] - -jobs: - lint-pr-title: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Install Dependencies - run: npm install @commitlint/config-conventional@v17 - - uses: JulienKode/pull-request-name-linter-action@v0.5.0 diff --git a/test/e2e/helpers/actions.ts b/test/e2e/helpers/actions.ts index b9fabbcf..268978d7 100644 --- a/test/e2e/helpers/actions.ts +++ b/test/e2e/helpers/actions.ts @@ -13,3 +13,13 @@ export async function openRadicleViewContainer(workbench: Workbench) { await radicleViewControl?.openView() } + +export async function closeRadicleViewContainer(workbench: Workbench) { + const activityBar = workbench.getActivityBar() + await activityBar.wait() + + const radicleViewControl = await activityBar.getViewControl('Radicle') + await radicleViewControl?.wait() + + await radicleViewControl?.closeView() +} diff --git a/test/e2e/helpers/assertions.ts b/test/e2e/helpers/assertions.ts index 539d5c31..4bca11fb 100644 --- a/test/e2e/helpers/assertions.ts +++ b/test/e2e/helpers/assertions.ts @@ -23,6 +23,11 @@ export async function expectStandardSidebarViewsToBeVisible(workbench: Workbench return false } }, - { timeoutMsg: 'expected the standard sidebar views to be visible' }, + { + timeoutMsg: 'expected the standard sidebar views to be visible', + // TODO: zac fine tune these (globally?) + timeout: 20000, + interval: 500, + }, ) } diff --git a/test/e2e/specs/httpd.spec.ts b/test/e2e/specs/httpd.spec.ts new file mode 100644 index 00000000..57ee169b --- /dev/null +++ b/test/e2e/specs/httpd.spec.ts @@ -0,0 +1,79 @@ +import { browser } from '@wdio/globals' +import type { OutputView, Setting } from 'wdio-vscode-service' +import { Key } from 'webdriverio' +import { $ } from 'zx' +import { nodeHomePath } from '../constants/config' + +describe('Httpd', () => { + it('finds and uses radicle identity', async () => { + const workbench = await browser.getWorkbench() + await workbench.executeCommand('Show Everything Logged in the Output Panel') + const outputView = await workbench.getBottomBar().openOutputView() + + const settings = await workbench.openSettings() + const pathToNodeHomeSetting = await settings.findSetting( + 'Path To Node Home', + 'Radicle', + 'Advanced', + ) + + await browser.waitUntil(async () => { + await setTextSettingValue(pathToNodeHomeSetting, nodeHomePath ?? '') + + return (await getTextSettingValue(pathToNodeHomeSetting)) === nodeHomePath + }) + + const radSelf = await $`rad self` + console.log({ radSelf }) + + await expectOutputToContain(outputView, 'Using already unsealed Radicle identity') + }) +}) + +async function expectOutputToContain(outputView: OutputView, expected: string) { + await browser.waitUntil( + async () => { + /** + * The text in the output console is split by newlines, which can be affected by the size + * of the window. To avoid this, we join the text into a single string. + */ + const joinedText = (await outputView.getText()).join('') + console.log({ joinedText }) + + return joinedText.includes(expected) + }, + { + timeoutMsg: `expected the output text to contain "${expected}"`, + }, + ) +} + +/** + * Workaround to get the value of a `TextSetting`. + * The `getValue` method of a `TextSetting` seems to be wrongly implemented and returns null. + */ +async function getTextSettingValue(setting: Setting) { + return await setting.textSetting$.getValue() +} + +async function setTextSettingValue(setting: Setting, value: string) { + await clearTextSetting(setting) + await setting.setValue(value) +} + +async function clearTextSetting(setting: Setting) { + /** + * `.setValue('')` updates the value of the input but does not trigger an + * update in the extension. Not sure if this is a bug in the extension, vscode, or + * webdriverio. + * + * The following is a workaround that does trigger an update in the extension. + */ + if ((await getTextSettingValue(setting)) === '') { + return + } + + await setting.textSetting$.click() + await browser.keys([Key.Ctrl, 'a']) + await browser.keys(Key.Backspace) +} diff --git a/test/e2e/specs/onboarding.spec.ts b/test/e2e/specs/onboarding.spec.ts deleted file mode 100644 index fff8b4e2..00000000 --- a/test/e2e/specs/onboarding.spec.ts +++ /dev/null @@ -1,158 +0,0 @@ -import path from 'node:path' -import { browser, expect } from '@wdio/globals' -import type { Workbench } from 'wdio-vscode-service' -import { $, cd } from 'zx' -import type * as VsCode from 'vscode' -import isEqual from 'lodash/isEqual' -import { expectStandardSidebarViewsToBeVisible } from '../helpers/assertions' -import { openRadicleViewContainer } from '../helpers/actions' -import { getFirstWelcomeViewText } from '../helpers/queries' -import { backupNodeHomePath, e2eTestDirPath, nodeHomePath } from '../constants/config' - -describe('Onboarding Flow', () => { - let workbench: Workbench - - before(async () => { - workbench = await browser.getWorkbench() - }) - - describe('VS Code, *before* Radicle is installed,', () => { - after(async () => { - await $`mv ${backupNodeHomePath} ${nodeHomePath}` - await workbench.executeCommand('Developer: Reload Window') - }) - - it('has our Radicle extension installed and available', async () => { - const extensions = await browser.executeWorkbench( - (vscode: typeof VsCode) => vscode.extensions.all, - ) - - expect( - extensions.some((extension) => extension.id === 'radicle-ide-plugins-team.radicle'), - ).toBe(true) - }) - - it('shows the Radicle button in the Activity Bar', async () => { - const radicleViewControl = await workbench.getActivityBar().getViewControl('Radicle') - const title = await radicleViewControl?.getTitle() - - expect(title).toBe('Radicle') - }) - - it('instructs the user to install radicle', async () => { - await openRadicleViewContainer(workbench) - - const welcomeText = await getFirstWelcomeViewText(workbench) - const buttonTitles = await getFirstWelcomeViewButtonTitles(workbench) - - expect(welcomeText).toEqual([ - /* eslint-disable max-len */ - 'Failed resolving the Radicle CLI binary.', - "Please ensure it is installed on your machine and either that it is globally accessible in the shell as `rad` or that its path is correctly defined in the extension's settings.", - "Please expect the extention's capabilities to remain severely limited until this issue is resolved.", - /* eslint-enable max-len */ - ]) - - expect(buttonTitles).toEqual(['Troubleshoot']) - }) - }) - - describe('VS Code, *before* the workspace is git-initialized,', () => { - it('guides the user on how to git-initialize their workspace', async () => { - await openRadicleViewContainer(workbench) - - await browser.waitUntil(async () => { - const welcomeText = await getFirstWelcomeViewText(workbench) - const welcomeButtonTitles = await getFirstWelcomeViewButtonTitles(workbench) - - return ( - isEqual(welcomeText, [ - /* eslint-disable max-len */ - 'The folder currently opened in your workspace is not a Git code repository.', - 'In order to use Radicle with it, this folder must first be initialized as a Git code repository.', - 'To learn more about how to use Git and source control in VS Code read the docs.', - /* eslint-enable max-len */ - ]) && - isEqual(welcomeButtonTitles, [ - 'Initialize Repository With Git', - 'Choose a Different Folder', - ]) - ) - }) - }) - }) - - describe('VS Code, *before* the workspace is rad-initialized,', () => { - before(async () => { - await initGitRepo() - }) - - it('guides the user on how to rad-initialize their git repo', async () => { - await openRadicleViewContainer(workbench) - - await browser.waitUntil(async () => { - const welcomeText = await getFirstWelcomeViewText(workbench) - - return isEqual(welcomeText, [ - /* eslint-disable max-len */ - 'The Git repository currently opened in your workspace is not yet initialized with Radicle.', - 'To use Radicle with it, please run `rad init` in your terminal.', - 'Once rad-initialized, this repo will have access to advanced source control, collaboration and project management capabilities powered by both Git and Radicle.', - 'During this reversible rad-initializing process you also get to choose whether your repo will be private or public, among other options.', - 'To learn more read the Radicle User Guide.', - /* eslint-enable max-len */ - ]) - }) - }) - }) - - describe('VS Code, *after* the workspace is rad-initialized,', () => { - before(async () => { - await $`rad init --private --default-branch main --name "A_test_blog" --description "Some repo" --no-confirm --verbose` - await workbench.executeCommand('Developer: Reload Window') - }) - - it('hides the non rad-initialized guide', async () => { - await browser.waitUntil(async () => { - const welcomeText = await getFirstWelcomeViewText(workbench) - - return welcomeText.some((text) => text.includes('rad init')) === false - }) - }) - - it('shows the standard sidebar views', async () => { - const sidebarView = workbench.getSideBar().getContent() - await sidebarView.wait() - - await expectStandardSidebarViewsToBeVisible(workbench) - }) - }) -}) - -async function initGitRepo() { - const repoDirPath = path.join(e2eTestDirPath, 'fixtures/workspaces/basic') - - await $`mkdir -p ${repoDirPath}` - cd(repoDirPath) - await $`git config --global init.defaultBranch main` - await $`git init .` - await $`git config --global user.email "test@radicle.xyz"` - await $`git config --global user.name "Radicle Test"` - await $`echo "# Basic Repo" > README.md` - await $`git add README.md` - await $`git commit -m 'adds readme' --no-gpg-sign` -} - -async function getFirstWelcomeViewButtonTitles(workbench: Workbench) { - const sidebarView = workbench.getSideBar().getContent() - await sidebarView.wait() - - const buttons = - (await (await (await sidebarView.getSections())[0]?.findWelcomeContent())?.getButtons()) ?? - [] - const buttonTitles = await Promise.all( - buttons.map(async (button) => await button.getTitle()), - ) - - return buttonTitles -} diff --git a/test/e2e/wdio.conf.ts b/test/e2e/wdio.conf.ts index d95a3414..1e1015e2 100644 --- a/test/e2e/wdio.conf.ts +++ b/test/e2e/wdio.conf.ts @@ -29,7 +29,7 @@ export const config: Options.Testrunner = { transpileOnly: true, }, }, - specs: ['./specs/**/*.ts'], + specs: ['./specs/httpd.spec.ts'], maxInstances: 10, capabilities: [ {