Skip to content

Commit

Permalink
chore(build-system-test): Merge web build system tests with canaries (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
esauerbo authored Oct 11, 2024
1 parent 5af986f commit e9d4fdc
Show file tree
Hide file tree
Showing 47 changed files with 3,657 additions and 206 deletions.
7 changes: 7 additions & 0 deletions .github/workflows/build-system-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ jobs:
uses: ./.github/workflows/reusable-build-system-test.yml
with:
dist-tag: latest
secrets:
AUTH_E2E_ROLE_ARN: ${{ secrets.AUTH_E2E_ROLE_ARN }}
DOMAIN: ${{ secrets.DOMAIN }}
PHONE_NUMBER: ${{ secrets.PHONE_NUMBER }}
USERNAME: ${{ secrets.USERNAME }}
NEW_PASSWORD: ${{ secrets.NEW_PASSWORD }}
VALID_PASSWORD: ${{ secrets.VALID_PASSWORD }}

log-failure-metric:
# Send a failure data point to metric BuildSystemTestFailure in github-workflows@ us-east-2
Expand Down
97 changes: 86 additions & 11 deletions .github/workflows/reusable-build-system-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,19 @@ on:
dist-tag:
required: true
type: string

secrets:
AUTH_E2E_ROLE_ARN:
required: true
DOMAIN:
required: true
PHONE_NUMBER:
required: true
USERNAME:
required: true
NEW_PASSWORD:
required: true
VALID_PASSWORD:
required: true
jobs:
build:
runs-on: ubuntu-latest
Expand All @@ -20,7 +32,6 @@ jobs:
build-tool: [next, vite]
build-tool-version: [latest]
pkg-manager: [npm]
language: [ts]
node-version: [20]
pkg-manager-version: [latest]
include:
Expand All @@ -29,60 +40,55 @@ jobs:
build-tool: next
build-tool-version: 13
pkg-manager: npm
language: ts
node-version: 20
- framework: react
framework-version: 18
build-tool: vite
build-tool-version: 3
pkg-manager: npm
language: ts
node-version: 20

- framework: angular
framework-version: latest
build-tool: angular-cli
build-tool-version: latest
pkg-manager: npm
language: ts
node-version: 20
- framework: angular
framework-version: 14
build-tool: angular-cli
build-tool-version: 14
pkg-manager: npm
language: ts
node-version: 20

- framework: vue
framework-version: 3 # here use "3" instead of "latest" because .vuerc(preset) doesn't accept "latest" as "vueVersion"
build-tool: vue-cli
build-tool-version: latest
pkg-manager: yarn # vue-cli defualt pkg-manager is yarn. It can't be customized in the preset.json.
language: ts
node-version: 20
- framework: vue
framework-version: latest
build-tool: vite
build-tool-version: latest
pkg-manager: npm
language: ts
node-version: 20
- framework: vue
framework-version: 3
build-tool: vite
build-tool-version: 3
pkg-manager: npm
language: ts
node-version: 20
- framework: vue
framework-version: latest
build-tool: nuxt
build-tool-version: latest
pkg-manager: npm
language: ts
node-version: 20

env:
MEGA_APP_NAME: ${{matrix.framework}}-${{ matrix.framework-version }}-${{ matrix.build-tool }}-${{ matrix.build-tool-version }}-ui-${{ inputs.dist-tag }}

steps:
- name: Checkout Amplify UI
uses: actions/checkout@b80ff79f1755d06ba70441c368a6fe801f5f3a62 # v4.1.3 https://github.com/actions/checkout/commit/cd7d8d697e10461458bc61a30d094dc601a8b017
Expand All @@ -95,7 +101,76 @@ jobs:
cache: ${{ matrix.pkg-manager }}
env:
SEGMENT_DOWNLOAD_TIMEOUT_MINS: 2
- name: Add Amplify CLI
run: yarn global add @aws-amplify/cli
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 https://github.com/aws-actions/configure-aws-credentials/commit/e3dd6a429d7300a6a4c196c26e071d42e0343502
with:
aws-region: us-east-2
role-to-assume: ${{ secrets.AUTH_E2E_ROLE_ARN }}
# Amplify CLI does not support headless pull with temporary credentials
# when useProfile is false.
# See: https://github.com/aws-amplify/amplify-cli/issues/11009.
- name: Create temp AWS profile
run: |
aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID && \
aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY && \
aws configure set aws_session_token $AWS_SESSION_TOKEN && \
aws configure set default.region $AWS_REGION
- name: Pull down AWS environments
run: npm run pull
working-directory: build-system-tests
- name: Delete AWS Profile
run: rm -rf ~/.aws
- name: Restore cypress runner from Cache
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 https://github.com/actions/cache/commit/0c45773b623bea8c8e75f6c82b208c3cf94ea4f9
id: restore-cypress-cache
with:
path: ~/.cache/Cypress
key: ${{ runner.os }}-canary-cypress-${{ hashFiles('build-system-tests/e2e/yarn.lock') }}
env:
SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1
- name: Create MegaApp ${{ env.MEGA_APP_NAME }} and run build on NodeJS ${{ matrix.node-version }}
run: npm run test:${{ matrix.framework }}:${{matrix.build-tool}} -- --framework-version ${{matrix.framework-version}} --build-tool-version ${{matrix.build-tool-version}} --pkg-manager ${{matrix.pkg-manager}} --tag ${{inputs.dist-tag}}
run: npm run setup:${{ matrix.framework }}:${{matrix.build-tool}} -- --framework-version ${{matrix.framework-version}} --build-tool-version ${{matrix.build-tool-version}} --pkg-manager ${{matrix.pkg-manager}} --tag ${{inputs.dist-tag}}
shell: bash
working-directory: build-system-tests
- name: Install e2e packages
uses: ./.github/actions/install-with-retries
with:
working-directory: build-system-tests/e2e
# If we got a cache hit on cypress runner, then we will skip cypress binary
# installation. Otherwise, it will install cypress binary.
skip-cypress-binary: ${{ steps.restore-cypress-cache.outputs.cache-hit }}
# If cypress cache was missed, then we need to create new cache entry and upload it.
# At this point, cypress runner should've been installed from the previous installation
# step, so we go ahead and update the cache entry.
- name: Cache cypress runner
if: steps.restore-cypress-cache.outputs.cache-hit != 'true'
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 https://github.com/actions/cache/commit/0c45773b623bea8c8e75f6c82b208c3cf94ea4f9
with:
path: ~/.cache/Cypress
key: ${{ runner.os }}-canary-cypress-${{ hashFiles('build-system-tests/e2e/yarn.lock') }}
env:
SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1
- name: Run E2E tests against ${{ env.MEGA_APP_NAME }} example
run: npm run test
id: e2e
working-directory: build-system-tests
env:
# Env values for testing flows
DOMAIN: ${{ secrets.DOMAIN }}
PHONE_NUMBER: ${{ secrets.PHONE_NUMBER }}
USERNAME: ${{ secrets.USERNAME }}
NEW_PASSWORD: ${{ secrets.NEW_PASSWORD }}
VALID_PASSWORD: ${{ secrets.VALID_PASSWORD }}
TAGS: '@${{ matrix.framework }}'

- name: Upload videos and screenshots
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 https://github.com/actions/upload-artifact/commit/0b7f8abb1508181956e8e162db84b466c27e18ce
if: ${{ failure() && steps.e2e.outcome != 'success' }}
with:
name: canary-cypress-error-${{ env.MEGA_APP_NAME }}
path: |
build-system-tests/e2e/cypress/videos/**
build-system-test/e2e/cypress/screenshots/**
retention-days: 5
5 changes: 5 additions & 0 deletions build-system-tests/e2e/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
DOMAIN=
NEW_PASSWORD=
PHONE_NUMBER=
USERNAME=
VALID_PASSWORD=
7 changes: 7 additions & 0 deletions build-system-tests/e2e/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# testing
cypress/fixtures/example.json
cypress/screenshots
cypress/videos


.env
35 changes: 35 additions & 0 deletions build-system-tests/e2e/cypress.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { addCucumberPreprocessorPlugin } from '@badeball/cypress-cucumber-preprocessor';
import createEsbuildPlugin from '@badeball/cypress-cucumber-preprocessor/esbuild';
import * as createBundler from '@bahmutov/cypress-esbuild-preprocessor';
import { defineConfig } from 'cypress';
import * as dotenv from 'dotenv';

dotenv.config();

export default defineConfig({
defaultCommandTimeout: 15000,
e2e: {
baseUrl: 'http://localhost:3000/',
specPattern: 'features/**/*.feature',

async setupNodeEvents(on, config) {
await addCucumberPreprocessorPlugin(on, config);

on(
'file:preprocessor',
createBundler({
define: { global: 'window' },
plugins: [createEsbuildPlugin(config)],
})
);

Object.assign(config.env, process.env);

return config;
},
},
env: {
tags: 'not @skip',
},
video: false,
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"CodeDeliveryDetails": {
"AttributeName": "email",
"DeliveryMedium": "EMAIL",
"Destination": "a***@e***.com"
},
"UserConfirmed": false,
"UserSub": "••••••-••••-••••-••••-•••••••••••••"
}
10 changes: 10 additions & 0 deletions build-system-tests/e2e/cypress/integration/common/liveness.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { When } from '@badeball/cypress-cucumber-preprocessor';

When(
'I request {string} and get {string}',
(url: string, statusCode: string) => {
cy.request({ url, followRedirect: true }).then(({ status }) => {
expect(status).to.be.equal(+statusCode);
});
}
);
55 changes: 55 additions & 0 deletions build-system-tests/e2e/cypress/integration/common/shared.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { Given, Then, When } from '@badeball/cypress-cucumber-preprocessor';

import { escapeRegExp } from 'lodash';

Given("I'm running the example {string}", (example: string) => {
cy.visit(example, {
// See: https://glebbahmutov.com/blog/cypress-tips-and-tricks/#control-navigatorlanguage
onBeforeLoad(win) {
Object.defineProperty(win.navigator, 'language', { value: 'en-US' });
},
});
});

Given(
'I intercept {string} with fixture {string}',
(json: string, fixture: string) => {
let routeMatcher;

try {
routeMatcher = JSON.parse(json);
} catch (error) {
throw error;
}

cy.intercept(routeMatcher, { fixture }).as('route');
}
);

When('I click the {string} tab', (label: string) => {
cy.findByRole('tab', {
name: new RegExp(`^${escapeRegExp(label)}$`, 'i'),
}).click();
});

When('I click the {string} button', (name: string) => {
cy.findByRole('button', {
name: new RegExp(`^${escapeRegExp(name)}$`, 'i'),
}).click();
});

Then('I see the {string} button', (name: string) => {
cy.findByRole('button', {
name: new RegExp(`^${escapeRegExp(name)}$`, 'i'),
}).should('be.visible');
});

Then('I see {string}', (message: string) => {
cy.findByRole('document')
.contains(new RegExp(escapeRegExp(message), 'i'))
.should('exist');
});

When('I type a new {string}', (field: string) => {
cy.findInputField(field).typeAliasWithStatus(field, `${Date.now()}`);
});
15 changes: 15 additions & 0 deletions build-system-tests/e2e/cypress/integration/common/sign-in.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { When } from '@badeball/cypress-cucumber-preprocessor';

When(
'I type my {string} with status {string}',
(loginMechanism: string, status: string) => {
cy.findInputField(loginMechanism).typeAliasWithStatus(
loginMechanism,
status
);
}
);

When('I type my password', () => {
cy.findInputField('Password').type(Cypress.env('VALID_PASSWORD'));
});
12 changes: 12 additions & 0 deletions build-system-tests/e2e/cypress/integration/common/sign-up.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Given, When } from '@badeball/cypress-cucumber-preprocessor';

Given('I click {string}', (text: string) => {
cy.findByText(text).click();
});

When('I confirm my password', () => {
cy.findInputField('Confirm Password')
.type(Cypress.env('VALID_PASSWORD'))
.blur()
.wait(100);
});
32 changes: 32 additions & 0 deletions build-system-tests/e2e/cypress/support/commands.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit e9d4fdc

Please sign in to comment.