feat(e2e): adding playwright and migrate landing page e2e tests (#51216)
Co-authored-by: Ahmad <57593864+Ahmadkashif@users.noreply.github.com> Co-authored-by: Hassaan Pasha <pasha.hassaan@gmail.com>pull/51228/head
parent
b9832f4029
commit
b5c86d4b9c
|
@ -10,4 +10,5 @@ config/donation-settings.js
|
|||
config/superblocks.js
|
||||
web/**
|
||||
docs/**/*.md
|
||||
tools/ui-components/dist/**
|
||||
tools/ui-components/dist/**
|
||||
playwright.config.ts
|
|
@ -74,7 +74,8 @@
|
|||
"./utils/tsconfig.json",
|
||||
"./web/tsconfig.json",
|
||||
"./curriculum-server/tsconfig.json",
|
||||
"./cypress/tsconfig.json"
|
||||
"./cypress/tsconfig.json",
|
||||
"./e2e/tsconfig.json"
|
||||
]
|
||||
},
|
||||
"extends": [
|
||||
|
@ -160,6 +161,14 @@
|
|||
"Cypress": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["e2e/*.ts"],
|
||||
"rules": {
|
||||
"@typescript-eslint/no-unsafe-member-access": "off",
|
||||
"@typescript-eslint/no-unsafe-call": "off",
|
||||
"@typescript-eslint/no-unsafe-assignment": "off"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["web/**/*.tsx"],
|
||||
"extends": ["plugin:react/jsx-runtime"]
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
name: CI - E2E - Playwright
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
branches:
|
||||
- 'main'
|
||||
- 'e2e-**'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
branches:
|
||||
- 'main'
|
||||
- 'next-**'
|
||||
- 'e2e-**'
|
||||
|
||||
jobs:
|
||||
build-client:
|
||||
name: Build
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [18.x]
|
||||
|
||||
steps:
|
||||
- name: Checkout Source Files
|
||||
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3
|
||||
|
||||
- name: Checkout client-config
|
||||
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3
|
||||
with:
|
||||
repository: freeCodeCamp/client-config
|
||||
path: client-config
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: pnpm
|
||||
|
||||
- name: Set freeCodeCamp Environment Variables
|
||||
run: cp sample.env .env
|
||||
|
||||
- name: Install and Build
|
||||
run: |
|
||||
pnpm install
|
||||
pnpm run build
|
||||
|
||||
- name: Move serve.json to Public Folder
|
||||
run: cp client-config/serve.json client/public/serve.json
|
||||
|
||||
# We tar them for performance reasons - uploading a lot of files is slow.
|
||||
- name: Tar Files
|
||||
run: tar -cf client-artifact.tar client/public
|
||||
|
||||
- name: Upload Client Artifact
|
||||
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3
|
||||
with:
|
||||
name: client-artifact
|
||||
path: client-artifact.tar
|
||||
|
||||
- name: Upload Webpack Stats
|
||||
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3
|
||||
with:
|
||||
name: webpack-stats
|
||||
path: client/public/stats.json
|
||||
|
||||
playwright-run:
|
||||
name: E2E Test
|
||||
runs-on: ubuntu-20.04
|
||||
needs: build-client
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
browsers: [chromium, firefox, webkit]
|
||||
node-version: [18.x]
|
||||
|
||||
services:
|
||||
mongodb:
|
||||
image: mongo:4.4
|
||||
ports:
|
||||
- 27017:27017
|
||||
# We need mailhog to catch any emails the api tries to send.
|
||||
mailhog:
|
||||
image: mailhog/mailhog
|
||||
ports:
|
||||
- 1025:1025
|
||||
|
||||
steps:
|
||||
- name: Set Action Environment Variables
|
||||
run: |
|
||||
echo "GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}" >> $GITHUB_ENV
|
||||
|
||||
- name: Checkout Source Files
|
||||
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3
|
||||
|
||||
- uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3
|
||||
with:
|
||||
name: client-artifact
|
||||
|
||||
- name: Unpack Client Artifact
|
||||
run: |
|
||||
tar -xf client-artifact.tar
|
||||
rm client-artifact.tar
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: Set freeCodeCamp Environment Variables
|
||||
run: cp sample.env .env
|
||||
|
||||
- name: Install and Build
|
||||
run: |
|
||||
pnpm install
|
||||
pnpm run create:config
|
||||
pnpm run build:curriculum
|
||||
pnpm run build:server
|
||||
|
||||
- name: Seed Database
|
||||
run: pnpm run seed
|
||||
|
||||
# start-ci uses pm2, so it needs to be installed globally
|
||||
- name: Install pm2
|
||||
run: npm i -g pm2
|
||||
|
||||
- name: Install playwright dependencies
|
||||
run: |
|
||||
cd ./e2e
|
||||
npm i
|
||||
npx playwright install
|
||||
npx playwright install-deps
|
||||
cd ..
|
||||
|
||||
- name: Run playwright tests
|
||||
run: |
|
||||
pnpm run start-ci &
|
||||
sleep 10
|
||||
cd ./e2e
|
||||
npx playwright test --project=${{ matrix.browsers }}
|
|
@ -230,3 +230,9 @@ client/src/components/Donation/types.js
|
|||
|
||||
### UI Components ###
|
||||
tools/ui-components/dist
|
||||
/test-results/
|
||||
/playwright-report/
|
||||
/playwright/.cache/
|
||||
test-results/
|
||||
playwright-report/
|
||||
/playwright/.cache/
|
||||
|
|
|
@ -0,0 +1,175 @@
|
|||
# How to add Playwright tests
|
||||
|
||||
## Installation:
|
||||
|
||||
To install and configure Playwright on your machine check out this [documentation](https://playwright.dev/docs/intro#installing-playwright)
|
||||
|
||||
To learn how to write Playwright tests, or 'specs', please see Playwright's official [documentation](https://playwright.dev/docs/writing-tests).
|
||||
|
||||
## Where to Add a Test
|
||||
|
||||
- Playwright tests are in the `./e2e` directory.
|
||||
|
||||
- Playwright test files are always with a `.spec.ts` extension.
|
||||
|
||||
## How to Run Tests
|
||||
|
||||
|
||||
### 1. Ensure that MongoDB and Client Applications are Running
|
||||
|
||||
- [Start MongoDB and seed the database](how-to-setup-freecodecamp-locally.md#step-3-start-mongodb-and-seed-the-database)
|
||||
|
||||
- [Start the freeCodeCamp client application and API server](how-to-setup-freecodecamp-locally.md#step-4-start-the-freecodecamp-client-application-and-api-server)
|
||||
|
||||
### 2. Run the Playwright Tests
|
||||
|
||||
To run tests with Playwright check the following below
|
||||
|
||||
- To run tests in UI helper mode:
|
||||
|
||||
```console
|
||||
npx playwright test --ui
|
||||
```
|
||||
|
||||
- To run a single test:
|
||||
|
||||
```console
|
||||
npx playwright test <filename>
|
||||
```
|
||||
|
||||
For example:
|
||||
|
||||
```console
|
||||
npx playwright test landing-page.spec.ts
|
||||
```
|
||||
|
||||
- Run a set of test files in respective folders:
|
||||
|
||||
```console
|
||||
npx playwright test <pathToFolder1> <pathToFolder2>
|
||||
```
|
||||
|
||||
For example:
|
||||
```console
|
||||
npx playwright test tests/todo-page/ tests/landing-page/
|
||||
```
|
||||
|
||||
- Run the test with the title:
|
||||
|
||||
```console
|
||||
npx playwright test -g <title>
|
||||
```
|
||||
|
||||
For example:
|
||||
```console
|
||||
npx playwright test -g "add a todo item"
|
||||
```
|
||||
|
||||
### 3. Debugging Tests
|
||||
|
||||
Since Playwright runs in Node.js, you can debug it with your debugger of choice e.g. using console.log or inside your IDE
|
||||
|
||||
- Debugging all tests:
|
||||
|
||||
```console
|
||||
npx playwright test --debug
|
||||
```
|
||||
|
||||
- Debugging one test file:
|
||||
|
||||
```console
|
||||
npx playwright test example.spec.ts --debug
|
||||
```
|
||||
|
||||
### 4. Generate Test Reports
|
||||
|
||||
The HTML Reporter shows you a full report of your tests allowing you to filter the report by browsers, passed tests, failed tests, skipped tests and flaky tests.
|
||||
|
||||
```console
|
||||
npx playwright show-report
|
||||
```
|
||||
|
||||
### 5. Troubleshooting
|
||||
|
||||
Playwright is generally a solid bullet-proof tool. The contributor has already configured the tests to run on all OS machines, including majpr distributions of Windows, MacOS and Linux.
|
||||
|
||||
|
||||
- A common error seen in playwright is as follows:
|
||||
|
||||
```console
|
||||
Error: page.goto: Could not connect: Connection refused
|
||||
=========================== logs ===========================
|
||||
navigating to "https://127.0.0.1:8000/", waiting until "load"
|
||||
============================================================
|
||||
```
|
||||
|
||||
You can fix the above error with the following steps:
|
||||
|
||||
1. **Check the URL:** Ensure that the URL you're trying to navigate to is correct and properly formatted. Make sure there are no typos in the URL.
|
||||
|
||||
2. **Server Status:** Check whether the server at the URL is running and accessible. You might encounter this error if the server is not running or is not accessible.
|
||||
|
||||
3. **Port Availability:** Verify that the port mentioned in the URL (8000 in this case) is the correct port and is available for use. Make sure no other process is already using that port.
|
||||
|
||||
4. **Firewall or Security Software:** Sometimes, firewall or security software can block connections to specific ports. Check your firewall settings to ensure that the port is allowed.
|
||||
|
||||
5. **Network Connectivity:** Ensure that your system has a working network connection and can access external resources.
|
||||
|
||||
- Another common error seen in playwright is as follows:
|
||||
|
||||
```console
|
||||
Protocol error (Network.getResponseBody): Request content was evicted from inspector cache
|
||||
```
|
||||
1. The network request was made using a method that does not include a response body, such as HEAD or CONNECT.
|
||||
2. The network request was made over a secure (HTTPS) connection, and the response body is not available for security reasons.
|
||||
3. The network request was made by a third-party resource (such as an advertisement or a tracking pixel) that is not controlled by the script.
|
||||
4. The network request was made by a script that has been paused or stopped before the response was received.
|
||||
|
||||
|
||||
|
||||
**For more insights on issues visit the official documentation.**
|
||||
|
||||
## Playwright-Gitpod Setup
|
||||
|
||||
### 1. Ensure Development Environment is Running
|
||||
|
||||
If starting the Gitpod environment did not automatically develop the environment:
|
||||
|
||||
- Follow the [MongoDB installation guide](https://www.mongodb.com/basics/get-started).
|
||||
|
||||
- Create the .env
|
||||
```console
|
||||
cp sample.env .env
|
||||
```
|
||||
|
||||
- Create a config file.
|
||||
```console
|
||||
pnpm run create:config
|
||||
```
|
||||
|
||||
- Seed the database
|
||||
```console
|
||||
pnpm run seed
|
||||
```
|
||||
|
||||
- Develop the server and client
|
||||
```console
|
||||
pnpm run develop
|
||||
```
|
||||
|
||||
### 2. Install Playwright Build Tools
|
||||
|
||||
To install necessary dependencies for running Playwright run the following command:
|
||||
|
||||
```console
|
||||
pnpm run playwright:install-build-tools
|
||||
```
|
||||
|
||||
|
||||
### 3. Run the Playwright Tests on Gitpod
|
||||
|
||||
To run all Playwright tests, run the following command:
|
||||
|
||||
```console
|
||||
npx playwright test
|
||||
```
|
|
@ -0,0 +1,90 @@
|
|||
import { test, expect, type Page } from '@playwright/test';
|
||||
|
||||
const landingPageElements = {
|
||||
heading: 'landing-header',
|
||||
callToAction: 'landing-big-cta',
|
||||
certifications: 'certifications',
|
||||
curriculumBtns: 'curriculum-map-button',
|
||||
testimonials: 'testimonial-card',
|
||||
landingPageImage: 'landing-page-figure',
|
||||
faq: 'landing-page-faq'
|
||||
} as const;
|
||||
|
||||
let page: Page;
|
||||
|
||||
const superBlocks = [
|
||||
'Responsive Web Design',
|
||||
'JavaScript Algorithms and Data Structures',
|
||||
'Front End Development Libraries',
|
||||
'Data Visualization',
|
||||
'Relational Database',
|
||||
'Back End Development and APIs',
|
||||
'Quality Assurance',
|
||||
'Scientific Computing with Python',
|
||||
'Data Analysis with Python',
|
||||
'Information Security',
|
||||
'Machine Learning with Python',
|
||||
'College Algebra with Python',
|
||||
'Coding Interview Prep',
|
||||
'Project Euler',
|
||||
'Legacy Responsive Web Design'
|
||||
];
|
||||
|
||||
test.beforeAll(async ({ browser }) => {
|
||||
page = await browser.newPage();
|
||||
await page.goto('/');
|
||||
});
|
||||
|
||||
test.afterAll(async () => {
|
||||
await page.close();
|
||||
});
|
||||
|
||||
test('Should render', async () => {
|
||||
await expect(page).toHaveTitle(
|
||||
'Learn to Code — For Free — Coding Courses for Busy People'
|
||||
);
|
||||
const callToAction = page.getByTestId(landingPageElements.callToAction);
|
||||
const callToActionHeader = page.locator('a .login-btn-text').nth(1);
|
||||
await expect(callToActionHeader).toHaveText("Get started (it's free)");
|
||||
await expect(callToAction).toHaveCount(4);
|
||||
});
|
||||
|
||||
test('Has visible header and sub-header', async () => {
|
||||
const heading = page.getByTestId(landingPageElements.heading);
|
||||
await expect(heading).toContainText('Learn to code — for free.');
|
||||
expect(await page.isVisible('text=Build projects.')).toBeTruthy();
|
||||
expect(await page.isVisible('text=Earn certifications.')).toBeTruthy();
|
||||
expect(
|
||||
await page.isVisible(
|
||||
'text=Since 2014, more than 40,000 freeCodeCamp.org ' +
|
||||
'graduates have gotten jobs at tech companies including:'
|
||||
)
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
test('Has 5 brand logos', async () => {
|
||||
await expect(page.locator('#featured-logos')).toBeVisible();
|
||||
});
|
||||
|
||||
test('Has `as seen in` section', async () => {
|
||||
await expect(page.locator('.as-seen-in')).toBeVisible();
|
||||
});
|
||||
|
||||
test('Has links to all superblocks', async () => {
|
||||
const curriculumBtns = page.getByTestId(landingPageElements.curriculumBtns);
|
||||
await expect(curriculumBtns).toHaveCount(15);
|
||||
superBlocks.map(async (cert, i) => {
|
||||
const btn = curriculumBtns.nth(i);
|
||||
await expect(btn).toContainText(cert);
|
||||
});
|
||||
});
|
||||
|
||||
test('Has 3 testimonial cards', async () => {
|
||||
const testimonials = page.locator(`.${landingPageElements.testimonials}`);
|
||||
await expect(testimonials).toHaveCount(3);
|
||||
});
|
||||
|
||||
test('Has FAQ section', async () => {
|
||||
const faqs = page.getByTestId(landingPageElements.faq);
|
||||
await expect(faqs).toHaveCount(9);
|
||||
});
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"name": "e2e",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.36.2",
|
||||
"@types/node": "^20.4.9"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
import { defineConfig, devices } from '@playwright/test';
|
||||
|
||||
/**
|
||||
* Read environment variables from file.
|
||||
* https://github.com/motdotla/dotenv
|
||||
*/
|
||||
// require('dotenv').config();
|
||||
|
||||
/**
|
||||
* See https://playwright.dev/docs/test-configuration.
|
||||
*/
|
||||
export default defineConfig({
|
||||
testDir: './',
|
||||
/* Run tests in files in parallel */
|
||||
fullyParallel: false,
|
||||
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||
forbidOnly: !!process.env.CI,
|
||||
/* Retry on CI only */
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
/* Opt out of parallel tests on CI. */
|
||||
workers: 1,
|
||||
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||
reporter: 'html',
|
||||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||
timeout: 15 * 1000,
|
||||
|
||||
use: {
|
||||
/* Base URL to use in actions like `await page.goto('/')`. */
|
||||
baseURL: process.env.HOME_LOCATION || 'http://127.0.0.1:8000',
|
||||
|
||||
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||
trace: 'on-first-retry',
|
||||
|
||||
/* Use custom test attribute */
|
||||
testIdAttribute: 'data-test-label'
|
||||
},
|
||||
|
||||
/* Configure projects for major browsers */
|
||||
projects: [
|
||||
{
|
||||
name: 'chromium',
|
||||
use: { ...devices['Desktop Chrome'] }
|
||||
},
|
||||
|
||||
{
|
||||
name: 'firefox',
|
||||
use: { ...devices['Desktop Firefox'] }
|
||||
},
|
||||
|
||||
{
|
||||
name: 'webkit',
|
||||
use: { ...devices['Desktop Safari'] }
|
||||
},
|
||||
|
||||
/* Test against mobile viewports. */
|
||||
{
|
||||
name: 'Mobile Chrome',
|
||||
use: { ...devices['Pixel 5'] }
|
||||
},
|
||||
{
|
||||
name: 'Mobile Safari',
|
||||
use: { ...devices['iPhone 12'] }
|
||||
}
|
||||
/* Uncomment the blocks out if you want to enable the mentioned features */
|
||||
/* ====================================================== */
|
||||
/* Test against branded browsers. */
|
||||
// {
|
||||
// name: 'Microsoft Edge',
|
||||
// use: { ...devices['Desktop Edge'], channel: 'msedge' }
|
||||
// },
|
||||
// {
|
||||
// name: 'Google Chrome',
|
||||
// use: { ...devices['Desktop Chrome'], channel: 'chrome' }
|
||||
// }
|
||||
]
|
||||
|
||||
/* Run your local dev server before starting the tests */
|
||||
// webServer: {
|
||||
// command: 'npm run start',
|
||||
// url: 'http://127.0.0.1:3000',
|
||||
// reuseExistingServer: !process.env.CI,
|
||||
// },
|
||||
});
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": ["es5", "dom", "ES2017"],
|
||||
"types": ["@playwright/test", "node"]
|
||||
},
|
||||
"extends": "../tsconfig-base.json"
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
module.exports = {
|
||||
testPathIgnorePatterns: ['/node_modules/', 'api/'],
|
||||
testPathIgnorePatterns: ['/node_modules/', 'api/', 'e2e/'],
|
||||
moduleNameMapper: {
|
||||
'\\.(jpg|jpeg|png|svg|woff|woff2)$':
|
||||
'<rootDir>/client/src/__mocks__/file-mock.ts',
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
"lint:prettier": "prettier --list-different .",
|
||||
"reload:server": "pm2 reload api-server/ecosystem.config.js",
|
||||
"preseed": "npm-run-all create:*",
|
||||
"playwright:install-build-tools": "sh ./playwright-install.sh && cd ./e2e && npm i && npx playwright install && npx playwright install-deps",
|
||||
"seed": "cross-env DEBUG=fcc:* node ./tools/scripts/seed/seed-demo-user",
|
||||
"seed:certified-user": "cross-env DEBUG=fcc:* node ./tools/scripts/seed/seed-demo-user certified-user",
|
||||
"seed:exams": "cd tools/scripts/seed-exams && cross-env node ./create-exams.js",
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
InstallKernelDependencies() {
|
||||
sudo apt-get install -y \
|
||||
libx11-xcb1 \
|
||||
libxrandr2 \
|
||||
libxcomposite1 \
|
||||
libxcursor1 \
|
||||
libxdamage1 \
|
||||
libxfixes3 \
|
||||
libxi6 \
|
||||
libxtst6 \
|
||||
libgtk-3-0 \
|
||||
libatk1.0-0 \
|
||||
libdbus-glib-1-2
|
||||
}
|
||||
|
||||
InstallKernelDependencies
|
|
@ -35216,4 +35216,4 @@ packages:
|
|||
resolution: {integrity: sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==}
|
||||
|
||||
/zwitch@2.0.4:
|
||||
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
|
||||
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
|
|
@ -256,9 +256,10 @@ const Button = () => {
|
|||
};`);
|
||||
});
|
||||
|
||||
/* Revisit this once we've decided what to do about multifile imports. I
|
||||
think the best approach is likely to be use the following format for .files
|
||||
|
||||
it('combines all the code of a specific language into a single file', () => {
|
||||
/* Revisit this once we've decided what to do about multifile imports. I
|
||||
think the best approach is likely to be use the following format for .files
|
||||
|
||||
{ css: [css files],
|
||||
html: [html files],
|
||||
|
@ -274,8 +275,9 @@ const Button = () => {
|
|||
|
||||
depending on what's easier to work with in graphQL
|
||||
|
||||
*/
|
||||
});
|
||||
|
||||
*/
|
||||
|
||||
it('should throw an error if a seed has no contents', () => {
|
||||
expect.assertions(1);
|
||||
|
|
Loading…
Reference in New Issue