Skip to content

Commit

Permalink
Linter script (#28)
Browse files Browse the repository at this point in the history
* Add prettier

* Run format scripts

* Add script to run linter

* Fix scripts + add format step in action

* Bump version
  • Loading branch information
bb-face authored Jul 2, 2024
1 parent 9608b0a commit b10c132
Show file tree
Hide file tree
Showing 19 changed files with 225 additions and 156 deletions.
14 changes: 7 additions & 7 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"customizations": {
"vscode": {
"extensions": ["github.vscode-github-actions", "ms-playwright.playwright"]
}
},
"postCreateCommand": "./.devcontainer/post-create.sh"
}
"customizations": {
"vscode": {
"extensions": ["github.vscode-github-actions", "ms-playwright.playwright"]
}
},
"postCreateCommand": "./.devcontainer/post-create.sh"
}
2 changes: 1 addition & 1 deletion .github/workflows/npm-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- uses: actions/setup-node@v3
with:
node-version: 20
registry-url: 'https://registry.npmjs.org'
registry-url: "https://registry.npmjs.org"
- run: yarn install
- run: yarn prod
- run: npm publish
Expand Down
7 changes: 5 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
name: CI
on:
push:
branches: [ main ]
branches: [main]
pull_request:
branches: [ main ]
branches: [main]
jobs:
test:
name: Playwright test
Expand All @@ -27,6 +27,9 @@ jobs:
- name: Install dependencies
run: yarn install

- name: Format code
run: yarn fmt

# Cache Playwright browsers
- name: Cache Playwright browsers
uses: actions/cache@v3
Expand Down
2 changes: 0 additions & 2 deletions .gitpod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,3 @@
tasks:
- init: yarn install && yarn run build
command: yarn run start


4 changes: 4 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
dist
node_modules
public
test-results
6 changes: 6 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"trailingComma": "es5",
"tabWidth": 2,
"semi": true,
"singleQuote": false
}
46 changes: 30 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,21 @@ This is a Proof of Concept of embedding a NEAR BOS widget into any web applicati
Just load react production react bundles into your index.html as shown below, and use the `near-social-viewer` custom element to embed the BOS widget.

```html
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Near social</title>
<script defer="defer" src="/runtime.REPLACE_WITH_BUNDLE_HASH.bundle.js"></script>
<script defer="defer" src="/main.REPLACE_WITH_BUNDLE_HASH.bundle.js"></script></head>
<script
defer="defer"
src="/runtime.REPLACE_WITH_BUNDLE_HASH.bundle.js"
></script>
<script
defer="defer"
src="/main.REPLACE_WITH_BUNDLE_HASH.bundle.js"
></script>
</head>
<body>
<h1>NEAR BOS embeddable custom element</h1>
<near-social-viewer></near-social-viewer>
Expand Down Expand Up @@ -50,11 +57,11 @@ yarn serve prod

The `near-social-viewer` web component supports several attributes:

* `src`: the src of the widget to render (e.g. `devs.near/widget/default`)
* `code`: raw, valid, stringified widget code to render (e.g. `"return <p>hello world</p>"`)
* `initialprops`: initial properties to be passed to the rendered widget.
* `rpc`: rpc url to use for requests within the VM
* `network`: network to connect to for rpc requests & wallet connection
- `src`: the src of the widget to render (e.g. `devs.near/widget/default`)
- `code`: raw, valid, stringified widget code to render (e.g. `"return <p>hello world</p>"`)
- `initialprops`: initial properties to be passed to the rendered widget.
- `rpc`: rpc url to use for requests within the VM
- `network`: network to connect to for rpc requests & wallet connection

## Configuring VM Custom Elements

Expand Down Expand Up @@ -124,7 +131,7 @@ In general it is a good practice, and very helpful for reviewers and users of th
The NEAR social VM supports a feature called `redirectMap` which allows you to load widgets from other sources than the on chain social db. An example redirect map can look like this:

```json
{"devhub.near/widget/devhub.page.feed": {"code": "return 'hello';"}}
{ "devhub.near/widget/devhub.page.feed": { "code": "return 'hello';" } }
```

The result of applying this redirect map is that the widget `devhub.near/widget/devhub.page.feed` will be replaced by a string that says `hello`.
Expand Down Expand Up @@ -156,15 +163,22 @@ We can obtain this by setting the `src` attribute pointing to the component we w
An example of this can be found in [router.spec.js](./playwright-tests/tests/router.spec.js).

```javascript
test("for supporting SEO friendly URLs, it should be possible to set initialProps and src widget from any path", async ({ page }) => {
test("for supporting SEO friendly URLs, it should be possible to set initialProps and src widget from any path", async ({
page,
}) => {
await page.goto("/community/webassemblymusic");
await page.evaluate(() => {
const viewerElement = document.querySelector('near-social-viewer');
const viewerElement = document.querySelector("near-social-viewer");
viewerElement.setAttribute("src", "devhub.near/widget/app");
const pathparts = location.pathname.split("/");
viewerElement.setAttribute("initialProps", JSON.stringify({ page: pathparts[1], handle: pathparts[2] }));
viewerElement.setAttribute(
"initialProps",
JSON.stringify({ page: pathparts[1], handle: pathparts[2] })
);
});
await expect(await page.getByText('WebAssembly Music', { exact: true })).toBeVisible();
await expect(
await page.getByText("WebAssembly Music", { exact: true })
).toBeVisible();
});
```

Expand All @@ -174,7 +188,7 @@ Here you can see that the viewer element `src` attribute is set to use the `devh

For testing how the library would work when used from CDN, you may publish it to NEARFS.

```bash
```bash
yarn nearfs:publish-library:create:car
```

Expand Down
2 changes: 1 addition & 1 deletion config/webpack.development.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const path = require("path");
const { HotModuleReplacementPlugin } = require("webpack");

module.exports = () => ({
devtool: 'inline-source-map',
devtool: "inline-source-map",
module: {
rules: [
{
Expand Down
4 changes: 2 additions & 2 deletions config/webpack.production.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ module.exports = () => {
minimizer: [
new CssMinimizerPlugin(),
new TerserPlugin({
exclude: /webcomponentapp.js/
})
exclude: /webcomponentapp.js/,
}),
],
runtimeChunk: {
name: "runtime",
Expand Down
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "near-bos-webcomponent",
"version": "0.0.9",
"version": "0.1.0",
"homepage": "https://github.com/NEARBuilders/near-bos-webcomponent",
"repository": {
"type": "git",
Expand All @@ -27,7 +27,7 @@
"local-storage": "^2.0.0",
"near-api-js": "^2.1.3",
"near-social-vm": "NearSocial/VM#2.6.1",
"prettier": "^2.7.1",
"prettier": "3.3.2",
"qrcode.react": "^3.1.0",
"react": "^18.2.0",
"react-bootstrap": "^2.5.0",
Expand All @@ -50,7 +50,9 @@
"test:ui": "npx playwright test --ui",
"test:ui:codespaces": "npx playwright test --ui-host=0.0.0.0",
"nearfs:publish-library:create:car": "ipfs-car pack dist/ --output dist.car",
"nearfs:publish-library:upload:car": "NODE_ENV=mainnet node ./node_modules/nearfs/scripts/upload-car.js dist.car"
"nearfs:publish-library:upload:car": "NODE_ENV=mainnet node ./node_modules/nearfs/scripts/upload-car.js dist.car",
"fmt": "prettier --write '**/*.{js,jsx,ts,tsx,json}'",
"fmt:check": "prettier --check '**/*.{js,jsx,ts,tsx,json}'"
},
"eslintConfig": {
"extends": [
Expand Down
2 changes: 1 addition & 1 deletion playwright-tests/storage-states/bos-loader-url.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@
}
],
"sessionStorage": []
}
}
86 changes: 47 additions & 39 deletions playwright-tests/tests/redirectmap.spec.js
Original file line number Diff line number Diff line change
@@ -1,47 +1,55 @@
import { test, describe, expect } from '@playwright/test';
import { test, describe, expect } from "@playwright/test";

describe("bos-loader-url", () => {
test.use({
storageState: "playwright-tests/storage-states/bos-loader-url.json"
});
test("Should be possible to provide a redirectmap through flags in localStorage", async ({
page,
}) => {
await page.route("http://localhost:3030", async (route) => {
await route.fulfill({
body: JSON.stringify(
{
components:
{
"something.near/widget/testcomponent":
{ "code": "return 'I come from a redirect map pointed to by flags in localStorage';" }
}
}
)
});
});
await page.goto("/something.near/widget/testcomponent");
await expect(page.getByText('I come from a redirect map pointed to by flags in localStorage')).toBeVisible();
test.use({
storageState: "playwright-tests/storage-states/bos-loader-url.json",
});
test("Should be possible to provide a redirectmap through flags in localStorage", async ({
page,
}) => {
await page.route("http://localhost:3030", async (route) => {
await route.fulfill({
body: JSON.stringify({
components: {
"something.near/widget/testcomponent": {
code: "return 'I come from a redirect map pointed to by flags in localStorage';",
},
},
}),
});
});
await page.goto("/something.near/widget/testcomponent");
await expect(
page.getByText(
"I come from a redirect map pointed to by flags in localStorage"
)
).toBeVisible();
});
});

describe("session-storage", () => {
test("Should be possible to provide a redirectmap through session storage key", async ({
page,
}) => {
await page.context().addInitScript(() => {
console.log('init script');
sessionStorage.setItem('nearSocialVMredirectMap', JSON.stringify(
{
"something.near/widget/testcomponent":
{ "code": "return 'I come from a redirect map from session storage';" }
}
));
})
await page.goto("/something.near/widget/testcomponent");
await page.evaluate(() => {
console.log(JSON.parse(sessionStorage.getItem("nearSocialVMredirectMap")))
test("Should be possible to provide a redirectmap through session storage key", async ({
page,
}) => {
await page.context().addInitScript(() => {
console.log("init script");
sessionStorage.setItem(
"nearSocialVMredirectMap",
JSON.stringify({
"something.near/widget/testcomponent": {
code: "return 'I come from a redirect map from session storage';",
},
})
await expect(await page.getByText('I come from a redirect map from session storage')).toBeVisible();
);
});
});
await page.goto("/something.near/widget/testcomponent");
await page.evaluate(() => {
console.log(
JSON.parse(sessionStorage.getItem("nearSocialVMredirectMap"))
);
});
await expect(
await page.getByText("I come from a redirect map from session storage")
).toBeVisible();
});
});
34 changes: 25 additions & 9 deletions playwright-tests/tests/router.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { expect, test } from "@playwright/test";
import { pauseIfVideoRecording, waitForSelectorToBeVisible } from "../testUtils";
import {
pauseIfVideoRecording,
waitForSelectorToBeVisible,
} from "../testUtils";

test("Verify default route loads successfully and displays expected content", async ({
page,
Expand Down Expand Up @@ -60,29 +63,42 @@ test("should load the other routes with params when provided", async ({
await pauseIfVideoRecording(page, 1000);
});

test("should be possible to set initialProps and src widget for the root path", async ({ page }) => {
test("should be possible to set initialProps and src widget for the root path", async ({
page,
}) => {
await page.goto("/");
await page.evaluate(() => {
document.body.innerHTML = `
<near-social-viewer src="devhub.near/widget/app" initialProps='{"page": "community", "handle": "webassemblymusic"}'></near-social-viewer>
`;
});
await expect(await page.getByText('WebAssembly Music', { exact: true })).toBeVisible({ timeout: 10000});
await expect(
await page.getByText("WebAssembly Music", { exact: true })
).toBeVisible({ timeout: 10000 });
});

test("for supporting SEO friendly URLs, it should be possible to set initialProps and src widget from any path", async ({ page }) => {
test("for supporting SEO friendly URLs, it should be possible to set initialProps and src widget from any path", async ({
page,
}) => {
await page.goto("/community/webassemblymusic");
await page.evaluate(() => {
const viewerElement = document.querySelector('near-social-viewer');
const viewerElement = document.querySelector("near-social-viewer");
viewerElement.setAttribute("src", "devhub.near/widget/app");
const pathparts = location.pathname.split("/");
viewerElement.setAttribute("initialProps", JSON.stringify({ page: pathparts[1], handle: pathparts[2] }));
viewerElement.setAttribute(
"initialProps",
JSON.stringify({ page: pathparts[1], handle: pathparts[2] })
);
});
await expect(await page.getByText('WebAssembly Music', { exact: true })).toBeVisible();
await expect(
await page.getByText("WebAssembly Music", { exact: true })
).toBeVisible();
});

test("should be able to load a widget from the path", async ({ page }) => {
await page.goto("/petersalomonsen.near/widget/aliens_close");
const playButton = await page.frameLocator('iframe').getByRole('button', { name: '▶' })
const playButton = await page
.frameLocator("iframe")
.getByRole("button", { name: "▶" });
await expect(playButton).toBeVisible();
});
});
2 changes: 1 addition & 1 deletion playwright-tests/tests/rpc.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ test("Verify custom RPC is called when provided", async ({ page }) => {
await waitForSelectorToBeVisible(page, "near-social-viewer");

let customRPCisCalledPromiseResolve;
let customRPCisCalled = new Promise(resolve => {
let customRPCisCalled = new Promise((resolve) => {
customRPCisCalledPromiseResolve = resolve;
});

Expand Down
Loading

0 comments on commit b10c132

Please sign in to comment.