diff --git a/.env.local b/.env.local deleted file mode 100644 index 80e142db2..000000000 --- a/.env.local +++ /dev/null @@ -1,4 +0,0 @@ -COMMERCE_PROVIDER=@vercel/commerce-shopify -NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN=e66b1627171548eabbb8aa425d085fc5 -NEXT_PUBLIC_SHOPIFY_STORE_DOMAIN=cypress-murat-shop.myshopify.com -NEXT_PUBLIC_COMMERCE_SEARCH_ENABLED=true diff --git a/.github/workflows/deployment.yml b/.github/workflows/deployment.yml new file mode 100644 index 000000000..ab787a5ca --- /dev/null +++ b/.github/workflows/deployment.yml @@ -0,0 +1,29 @@ +name: E2E on Chrome localhost:3000 + +on: + push: + branches: ['main'] + workflow_dispatch: # to test out if GITHUB_TOKEN env var can be a solution for rerunning CI and having it re-record on Cypress Dashboard + +jobs: + install: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + # Version 1: no parallelization + - name: Cypress run + uses: cypress-io/github-action@v3.0.4 + with: + browser: chrome + start: yarn dev + record: true + env: + COMMERCE_PROVIDER: ${{ secrets.COMMERCE_PROVIDER }} + NEXT_PUBLIC_SHOPIFY_STORE_DOMAIN: ${{ secrets.NEXT_PUBLIC_SHOPIFY_STORE_DOMAIN }} + NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN: ${{ secrets.NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN }} + NEXT_PUBLIC_COMMERCE_SEARCH_ENABLED: true + CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} + # pass GitHub token to allow accurately detecting a build vs a re-run build + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c519d303f..3eeef2d0e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,7 +1,7 @@ -name: E2E on Chrome +name: E2E on Chrome localhost:3000 on: - push: + pull_request: workflow_dispatch: # to test out if GITHUB_TOKEN env var can be a solution for rerunning CI and having it re-record on Cypress Dashboard jobs: @@ -28,58 +28,3 @@ jobs: CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} # pass GitHub token to allow accurately detecting a build vs a re-run build GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - ############################################################################################################################# - - # # Version 2: install in one job, parallelize the e2e jobs - # - name: Cypress install - # uses: cypress-io/github-action@v2 - # with: - # runTests: false - - # # probably Vercel relevant. No idea why we have to build anything - # # In version 1, I did not have to build anything to get things to work in CI - # # here, without the build job generating an artifact, the test jobs do not really get items related to our store - # - run: yarn build - # env: - # COMMERCE_PROVIDER: ${{ secrets.COMMERCE_PROVIDER }} - # NEXT_PUBLIC_SHOPIFY_STORE_DOMAIN: ${{ secrets.NEXT_PUBLIC_SHOPIFY_STORE_DOMAIN }} - # NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN: ${{ secrets.NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN }} - - # - name: Save build folder - # uses: actions/upload-artifact@v2 - # with: - # name: build - # if-no-files-found: error - # path: ./packages/**/dist/** - - # ui-chrome-tests: - # runs-on: ubuntu-latest - # needs: install - # strategy: - # fail-fast: false - # matrix: - # containers: [1, 2] - # steps: - # - name: Checkout - # uses: actions/checkout@v2 - - # # must be Vercel relevant. No idea why we have to build anything - # - name: Download the build folders - # uses: actions/download-artifact@v2 - # with: - # name: build - # path: ./packages/**/dist/** - - # - name: 'Chrome E2E Tests' - # uses: cypress-io/github-action@v2 - # with: - # browser: chrome - # start: yarn dev - # wait-on: 'http://localhost:3000' - # wait-on-timeout: 120000 - # record: true - # # spec: cypress/integration/* - # env: - # CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} - # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/cypress/config/dev.json b/cypress/config/dev.json new file mode 100644 index 000000000..d5fe9a446 --- /dev/null +++ b/cypress/config/dev.json @@ -0,0 +1,6 @@ +{ + "baseUrl": "https://nextjs-cypress-j6ls5tggc-muratkeremozcan.vercel.app/", + "viewportHeight": 1000, + "viewportWidth": 1280, + "projectId": "pefcjb" +} diff --git a/cypress/config/local.json b/cypress/config/local.json new file mode 100644 index 000000000..d7a538445 --- /dev/null +++ b/cypress/config/local.json @@ -0,0 +1,6 @@ +{ + "baseUrl": "http://localhost:3000", + "viewportHeight": 1000, + "viewportWidth": 1280, + "projectId": "pefcjb" +} diff --git a/package.json b/package.json index 1566df340..24c8e589c 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,10 @@ "start": "turbo run start", "types": "turbo run types", "prettier-fix": "prettier --write .", - "cypress:open": "cypress open", - "cypress:run": "cypress run" + "cy:open-local": "cypress open --config-file cypress/config/local.json", + "cy:run-local": "cypress run --config-file cypress/config/local.json", + "cy:open-dev": "cypress open --config-file cypress/config/dev.json", + "cy:run-dev": "cypress run --config-file cypress/config/dev.json" }, "devDependencies": { "cypress": "^9.6.0", diff --git a/site/comments.md b/site/comments.md index 486deecee..168eb2772 100644 --- a/site/comments.md +++ b/site/comments.md @@ -1,338 +1,88 @@ -# Feedback on Real World Testing with Cypress course +## Adding a config files to test the deployment -At Extend, Shopify is one of the merchants we integrate with to sell warranties (alongside BigCommerce and Magento), so this course is also domain relevant for learning. +Create a config folder and two json files `cypress/config/local.json`, `cypress/config/dev.json`. -I will capture any feedback here while going through the content, for the purpose of making the content as frictionless as possible, so that adoption is higher for Extend as well as any Cypress users who want to perform self-learning. - -TL, DR; the source repo is vastly different and environment variables are not possible to get to work as described. All the below are a consequence of that. I have included the .env.local file so that one can try to reproduce these issues. At the end, these issues can be figured out but it requires a high amount of know-how and willpower. We need to make it so that things work with batteries included, without having to wrestle anything. One should compare the below comments to the final version of the code while going through it. - -## [Part 1- Creating a Shopify Partners Store](https://learn.cypress.io/tutorials/creating-a-shopify-partners-store) - -Shopify must have made updates. One can figure out their way through it, but on Cypress side we need to update the screenshots and also slightly update the instructions. - -## [Part 2- Creating the Nex.js App](https://learn.cypress.io/tutorials/creating-the-next-js-app) - -Vercel must have made updates to their repo. There are many `tsconfig.json` files now, and the one we need is `./site/tsconfig.json` - -The `src` suffix is extra now, we are missing that in the current instructions. - -We have: +`local.json` file looks exactly like a copy of our root `cypress.json`. ```json -"@framework": ["framework/local"], -"@framework/*": ["framework/local/*"] -``` - -They have: - -```json -"@framework": ["../packages/local/src"], -"@framework/*": ["../packages/local/src/*"] -``` - -We have to aggregate `src` to our update instructions. - -We have: - -```json -"@framework": ["framework/shopify"], -"@framework/*": ["framework/shopify/*"] -``` - -We should have: - -```json -"@framework": ["framework/shopify/src"], -"@framework/*": ["framework/shopify/src/*"] -``` - ---- - -We should update the app screenshot as we launch localhost:3000 - ---- - -## [Part 3 - Writing e2e tests with Cypress](https://learn.cypress.io/tutorials/writing-end-to-end-tests-with-cypress) - -Not that I am a TS fanatic, it's good in places, but the cloned Vercel repo is in TS. At minimum we can refer to real world app or the docs for a TS setup reference. If the audience chooses to, we can make it easier for them. - ---- - -We want to show latest and greatest ways of writing Cypress code. There are certain reasons we might not be able to implement it -the helper `data-test` command may be difficult later- but we should do the due diligence and let the audience know about some knowledge they can use the the future as side notes. - -One side node we should insert here is below. - -Instead of this -`cy.get('[data-test="product-tag"]').eq(0)` -I would use -`cy.get('[data-test="product-tag"]:nth(0)')` - -It is less pretty, but it can be more stable with element-detached-from-the dom errors. -Recently I had to wrestle the CI for our own Shopify app at Extend with this exact issue. At minimum we can refer to this video https://www.youtube.com/watch?v=deNl1q1el0E, letting the audience know about these concerns. - ---- - -We can let the audience know if they have not used a duplicate name for their product, they may need to update this code. - -`cy.get('[data-test="product-name"]').should("contain", "Code Shirt")` - -That variance taken may also impact other string checks. Mine was like this: - -```js -describe('Home Page', () => { - it('displays all 3 products on the home page', () => { - cy.visit('http://localhost:3000') - cy.get('[data-test="product-tag"]') - .eq(0) - .within(() => { - cy.get('[data-test="product-name"]').should( - 'contain', - 'tshirt-stack-overflow' - ) - cy.get('[data-test="product-price"]').should('contain', '$25.00 USD') - }) - - cy.get('[data-test="product-tag"]') - .eq(1) - .within(() => { - cy.get('[data-test="product-name"]').should( - 'contain', - 'Lightweight Jacket' - ) - cy.get('[data-test="product-price"]').should('contain', '$249.99 USD') - }) - - cy.get('[data-test="product-tag"]') - .eq(2) - .within(() => { - cy.get('[data-test="product-name"]').should('contain', 'Shirt') - cy.get('[data-test="product-price"]').should('contain', '$25.00 USD') - }) - }) -}) -``` - ---- - -When checking the urls, we should use the opportunity to show off the documentation for `cy.location` when it gets introduced. "If you want to learn more about `cy.location`...". - ---- - -When the viewport is modified in `cypress.json`, perhaps it's a good opportunity to have the audience navigate to Settings > Configuration to confirm this change. This is a simple and solid troubleshooting tool. Also, another good excuse to link to the relevant docs. - ---- - -The app has changed, and `data-test="nav-link-hom-page">` is under a list. Therefore clicking it with the given code causes en error due to multiple elements. Instead of `eq(0)` or `first()` we can modify the attribute like this: - -```js { - links?.map((l) => ( - - - {l.label} - - - )) + "baseUrl": "http://localhost:3000", + "viewportHeight": 1000, + "viewportWidth": 1280, + "projectId": "pefcjb" } ``` -The attributes will look like: -`nav-link-home-page-New Arrivals` -`nav-link-home-page-Featured` +`dev.json` file has an updated `baseUrl` to represent our deployment. -And here we can also talk about `cy.getBySelLike()`, because if you want to go to _New Arrivals_, the space between the words would require taming the attribute, and we don't really want to do that so much. We can just use `cy.getBySelLike('nav-link-home-page-New').click()`. - -We have to update the `cy.location` path check as well. Here's the full code. - -```js -describe('Home Page', () => { - beforeEach(() => cy.visit('/')) - - it('displays all 3 products on the home page', () => { - cy.getBySel('product-tag') - .should('have.length.gte', 3) - .eq(0) - .within(() => { - cy.getBySel('product-name').should('contain', 'tshirt-stack-overflow') - cy.getBySel('product-price').should('contain', '$25.00 USD') - }) - - cy.getBySel('product-tag') - .eq(1) - .within(() => { - cy.getBySel('product-name').should( - 'contain', - 'tshirt-it-works-on-my-machine' - ) - cy.getBySel('product-price').should('contain', '$25.00 USD') - }) - - cy.getBySel('product-tag') - .eq(2) - .within(() => { - cy.getBySel('product-name').should('contain', 'tshirt-github') - cy.getBySel('product-price').should('contain', '$25.00 USD') - }) - }) -}) - - -describe('Header', () => { - it('links to the correct pages', () => { - cy.visit('http://localhost:3000') - cy.getBySel('logo').click() - cy.location('pathname').should('eq', '/') - - cy.getBySel('nav-link-search').click() - cy.location('pathname').should('eq', '/search') - - cy.getBySelLike('nav-link-home-page-New').click() - cy.location('pathname').should('eq', '/search/new-arrivals') - }) -}) +```json +{ + "baseUrl": "https://nextjs-cypress-j6ls5tggc-muratkeremozcan.vercel.app/", + "viewportHeight": 1000, + "viewportWidth": 1280, + "projectId": "pefcjb" +} ``` ---- +(How I wish we could *extend* the base `cypress.json`, because unfortunately Gleb's `cypress-extends` plugin clashes with other plugins like `cypress-grep`) -`components/common/Searchbar/Searchbar.tsx` is under `site` now. We should update to `site/components/common/Searchbar/Searchbar.tsx`. +We slightly modify our `package.json` scripts to use the respective config files: -For this to work, first we need a 4th environment variable in `.env.local`: - -``` -COMMERCE_PROVIDER=@vercel/commerce-shopify -NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxx -NEXT_PUBLIC_SHOPIFY_STORE_DOMAIN=xxxxxxxxxxxxxxxxxxxxxxxxxxxx -NEXT_PUBLIC_COMMERCE_SEARCH_ENABLED=true +```json +"scripts": { + "build": "turbo run build --scope=next-commerce --include-dependencies --no-deps", + "dev": "turbo run dev", + "start": "turbo run start", + "types": "turbo run types", + "prettier-fix": "prettier --write .", + "cy:open-local": "cypress open --config-file cypress/config/local.json", + "cy:run-local": "cypress run --config-file cypress/config/local.json", + "cy:open-dev": "cypress open --config-file cypress/config/dev.json", + "cy:run-dev": "cypress run --config-file cypress/config/dev.json" +}, ``` -Mind `COMMERCE_PROVIDER=@vercel/commerce-shopify` and not just `shopify`. This is in the main repo's readme. - -And we have to make the following change at `site/components/common/Navbar/Navbar.tsx`. -TL, DR; replace `process.env.COMMERCE_SEARCH_ENABLED` with `process.env.NEXT_PUBLIC_COMMERCE_SEARCH_ENABLED` - -Before: - -```js - {process.env.COMMERCE_SEARCH_ENABLED && ( -