Skip to content

Commit

Permalink
Solve merge conflicts from merge: master into v2.0.0-alpha.1 (#25)
Browse files Browse the repository at this point in the history
* Add support for strict CSP's (#8)

* Initial commit

* Initial commit

* Use babel-eslint parser to support arrow functions (and other)

* Use babel-eslint parser to support arrow functions (part 2)

* Intitial commit for components

* Add Api abstraction layer

This abstraction layer is the base layer which contains all the Api calls done with fetch().

* Add step comments to EventLog.jsx

* Add some comments to api scripts

* We dont have a release branch anymore (due to creating a new repo)

* Fix ESLint issues, especially no-invalid-this

no-invalid-this had to be replaced by @babel/no-invalid-this, otherwise it would show false positives in arrow functions

* Removed console logs and fixed `curly` rule to be used always

* Innitial commit for:
Announcement
Image.jsx
ImageViewer.jsx
ReplyActions.jsx

Removed
MarkdownText.jsx

Changed:
Arrow functions and removed binds
Disabled Image.jsx (not required in first version)

* Add build targets to package.json

* Remove babel presets that are handled automatically in Parcel beta 3

https://v2.parceljs.org/blog/beta3/

Had to install a plugin for eslint otherwise it showed errors because it is missing je react-preset

* Working on build targets

* Added .postcssrc for more control over CSS transformations

* Update readme with info about building

* Add CSP

* Pulled from /components

* Pulled from /build

* Create index.html with CSP

* Forgot to load the css stylesheet

* Add Cypress and Polling and first basic test

* Add unit tests for polling mechanism

* Implement PollingService in ApiEventTarget

And demo this in the example application

* Implement Polling Service in UI (because we don't use the logic in ApiEventTarget anymore)

* Add polling test for restartPolling()

* Fix regex

* Remove duplicated files

* Remove duplicated files

* Only stop(& restart) the polling interval when we go on to the next interval

If we keep the current interval there is no need to stop and restart..

* Reset variables when calling restartPolling()

* Remove unneeded dependency with account/deviceIdentification

* Rename stuff & fix issue with `currentIntervalAmount` being greater than the max

Also fixed last test for polling; it didn't stop after `resolve()` so it needed a `return`

* Remove config const for polling tests and let each test define their own

also lowered the intervals for the first test

* Use timeouts in Polling

* Rename message send event to "sent" (past tense)

* Rename interfaceTexts.js to tempConfig.js, becuase we will be storing config values aswell

Also disabled quickreplies

* Start polling when device is subscribed and reset polling when message is sent

Also added; Message sending on submit, Device registration when chat opens, Stop polling on unmount

* Disable input field while sending message to parley

* Remove comments about implementing stuff later

We have tickets and that should be enough

* Use ow package to validate params

* Rename var to timeout

* Remove commented console logs

* Wait for getMessages before continuing the next interval

* Forgot a variable

* Test polling reaction to api events

* Show messages in conversation

* Restart polling when there is focus on the input field

Also open the chat when there is a new message

* Fixed issue in code that finds a new message id

* Let Conversation.jsx restart polling when it mounts

This way you should always see your new messages when the conversation window opens

* Scroll down when there is a new message

* Suppress eslint error

When i remove this variable the IDEA complains about the override not being the same as the original..

* Only render Agent's name once if there are more agent messages

* Refocus input field after sending a message

* Updating axe-core

Was hoping this would fix it..

* Remove auto start of polling in constructor

Also clear event listeners on stopPolling()
And fixed tests

* Restart polling when page/window receives visibility/focus

* Fix scroll to bottom when new messages come in

Had to compare last id's instead of array lengths because the API gives out max 50 messages..

* Fix typo in test

* Merge

* Only load code-coverage code when in development mode

* (re)create index CSP file

* Turn default imports (css) into namespace imports

https://v2.parceljs.org/languages/postcss/#css-modules-tree-shaking

* Fix issue where CSS was not correctly build in index_CSP.html

* Dont check unused vars in args because they can conflict with phpstorm's "signature mismatch" inspection

* No need for a variable here

* Remove unused npmrc

* Use Parcel nightly for css scope hoisting fix

fix: parcel-bundler/parcel#6489
Also used parcel's babel presets as defined here: https://v2.parceljs.org/languages/babel/#extending-the-default-babel-config

* Remove idea gitignore (we have our own one)

* Revert change to parley-web-library.iml

* Remove pageVisibilityApi.js, we dont need it anymore

* Make sure fontawesome css is bundled in our css

so that we don't need to include it separately in the index.html

* Remove axe-core and fix csp

* Dont need postcss (installed automatically by Parcel)

* Fix building css finally

Co-authored-by: Gydo Titulaer <gydo.titulaer@tracebuzz.com>
Co-authored-by: Daan Leenders <daan@tracebuzz.com>

* Save device registration in storage (#9)

* Save device registration in local storage and check it upon `subscribeDevice()`

* Add ability to load settings from window.parleySettings (for now)

* Add start wrapper function for loading the chat in the advanced demo page (for now)

* Add css to index.html

* Use namespace imports for styles

* Use parcel's own babel presets

* Use css scoped names

* Fix issue with Parcel

* Add js for demo page (taken from v1 so not optimized, might also be temporary)

* Only load code coverage on development builds

* Compare localStorage device information with new one when calling subscribeDevice

when they both match, it means we don't have any new data for the api
so calling it would be a waste of resources.

* Add authorization and language options to demo

# Conflicts:
#	index.js
#	parleycdn-demo/index.html

* Add authorization and language options to demo

* Compare authorization before registering device

* Make storage prefix customizable

Somehow is also missed some npm packages so i needed to install those

* Add storage prefix from settings

* Update index.html

Co-authored-by: Daan Leenders <daanleenders@gmail.com>

Co-authored-by: Daan Leenders <daanleenders@gmail.com>

* Implements the configuration (#10)

* Fix problem where error notification returned a object and not just text

also added the use of `ApiGenericError` for errors when the API didn't provide one

* Add context providers

also handle/show errors in chat
also remove axe-core (doesn't work and keeps throwing errors)

* Add tests for ui errors

* Working changing language

* No need for contextType

* Create test for testing parley settings reactivity

* Make window.parleySettings reactive using Proxies

also; moved/renamed context.js => Scripts/Context.js
also; add a Logger for logging stuff with log levels

* When language changes, make sure the interfaceTexts overrides stay the same

when overriding interfaceTexts using `window.parleySettings.runOptions.interfaceTexts` and switching language, we don't want your custom overrides to get replaced by the InterfaceText.{language} defaults

* Create new Api instance (and device) when switching roomNumber

* Re-register device when authHeader changes

* Re-register device when userAdditionalInformation changes

* When infoText setting changes, the UI needs to change as well

Also; fixed issue where proxy would keep triggering `setState()` after being unmounted
Also; added eslint plugin to remove unused imports

* When placeholderMessenger setting changes, the UI needs to change as well

Also; added plugin to disallow `.only` tests

* Add some comments

* Change how Proxy works to make it more robust and easier to understand

Also; renamed v1 props to v2 in InterfaceTexts
Also; moved some functions around
Also; added jsdocs
Also; fixed issue where errorNotfication render gave an error that it didn't exist

* Add workingHours (weekdays) and hideChatOutsideWorkingHours (hideChatAfterBusinessHours) settings

Also; made them hide the Launcher if we are outside working hours and hideChatxxx is true
Also; Copied the script from v1 that checks if we are inside/outside working hours

* Add mobile recognition

* Add device version to state

* Move country to runOptions layer

* Authorization can't be empty when calling subscribeDevice()

* Fix issue where device version is empty if it didn't have pre-release tags

* Add hide button for error messages

* Default value for error message colors

* Load all interface texts default on construct

* Remove todo comments

* Set stylelint config path to auto-detect

somehow Phpstorm was messing up the path (probably because of a new update..)

* Remove unused css

* Rename referer to referrer if we are talking about anything other than the HTTP header / Api payload

* Remove unused var and remove optional params

* Make sure code coverage and index.html are CSP compliant

* Not sure why Phpstorm deleted this but i don't think it is important

* Data can be null if no messages are found, so it's better if we check if data is set

* Remove eslint rule `prefer-promise-reject-errors`

We don't need to throw an Error here with a stack trace because the API made the error so there is no stack trace that points to the API..

* Return `null` when get messages api call throws an error

* fix typo

* Remove event listener on unmount

* Make the api generic error configurable in the UI

* Make unit tests for working hours script

* Add code coverage for unit test

* Add missing tests so we reach ~99% code coverage

I can't test line 92 on workingHours.js because it checks the current date and to change that i need to change the system time..

* Install light-server to serve code coverage page with live reload

Couldn't use `parcel serve` for this because the index.html page contained multiple assets

* Use array destructuring for readability

* Use `toLocaleString()` so we don't need an extra array

* Make sure office hours are 24/7 otherwise tests will fail

* Add an extra test which tests the `false` part of the `format [day, start, end, false]` office hours format

* Add storagePrefix to state

* Use `componentDidUpdate()` instead of `shouldComponentUpdate()` because it is a better place for these checks

* Ignore stuff we don't need in the repo

* Forgot to change copied test

Also ignore gitlink

* Don't allow falsy values in the `state.messages`, it should always be an array

* Fix some bad merges

* Add functionality that clears your local messages if you don't have access (anymore) to the API

Co-authored-by: Gydo Titulaer <gydo.titulaer@tracebuzz.com>
Co-authored-by: Daan Leenders <daan@tracebuzz.com>
Co-authored-by: Daan Leenders <daanleenders@gmail.com>
  • Loading branch information
4 people committed Apr 26, 2022
1 parent 110b680 commit 169fe9c
Show file tree
Hide file tree
Showing 22 changed files with 12,414 additions and 9,459 deletions.
6 changes: 5 additions & 1 deletion .babelrc
Expand Up @@ -9,7 +9,11 @@
],
"env": {
"development": {
"plugins": ["istanbul"]
"plugins": [
["istanbul", {
"coverageGlobalScopeFunc": false
}]
]
}
}
}
1 change: 0 additions & 1 deletion .eslintrc.json
Expand Up @@ -110,7 +110,6 @@
"no-void": "error",
"no-warning-comments": "warn",
"prefer-named-capture-group": "error",
"prefer-promise-reject-errors": "error",
"prefer-regex-literals": ["error", {"disallowRedundantWrapping": true}],
"radix": ["error", "as-needed"],
"require-unicode-regexp": "error",
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Expand Up @@ -4,9 +4,14 @@
/.idea/shelf
# Datasource local storage ignored files
/.idea/dataSources/
/.idea/dataSources.xml
/.idea/dataSources.local.xml
# Editor-based HTTP Client requests
/.idea/httpRequests/
# Phpstorm files for php
/.idea/php.xml
# Plugins
/.idea/GitLink.xml

dist
lib
Expand Down
4 changes: 0 additions & 4 deletions .idea/dataSources.local.xml

This file was deleted.

5 changes: 5 additions & 0 deletions .idea/misc.xml

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

4 changes: 0 additions & 4 deletions .idea/php.xml

This file was deleted.

6 changes: 0 additions & 6 deletions .idea/stylesheetLinters/stylelint.xml

This file was deleted.

52 changes: 38 additions & 14 deletions cypress/integration/api-class_spec.js
Expand Up @@ -16,7 +16,7 @@ const config = {
type: Web,
version: "010000",
message: "test message",
referer: "weblib-v2_cypress-test",
storagePrefix: "customPrefix_",
};
const primitiveTypes = [
{
Expand Down Expand Up @@ -60,6 +60,7 @@ describe("Api class", () => {
config.accountIdentification,
config.deviceIdentification,
ApiEventTarget,
config.storagePrefix,
);

// Intercept api calls and respond with a static response
Expand All @@ -81,11 +82,23 @@ describe("Api class", () => {
expect(config.api.accountIdentification).to.be.equal(config.accountIdentification);
expect(config.api.deviceIdentification).to.be.equal(config.deviceIdentification);
expect(config.api.eventTarget).to.be.equal(ApiEventTarget);
expect(config.api.storagePrefix).to.be.equal(config.storagePrefix);
});
it("should throw an error when using something other than a EventTarget as apiEventTarget", () => {
expect(() => new Api(config.apiDomain, config.accountIdentification, config.deviceIdentification, {}))
.to.throw("Expected object `apiEventTarget` `{}` to be of type `EventTarget`");
});
describe("storagePrefix", () => {
it("should default to 'parley_'", () => {
const api = new Api(
config.apiDomain,
config.accountIdentification,
config.deviceIdentification,
ApiEventTarget,
);
expect(api.storagePrefix).to.be.equal("parley_");
});
});
});

describe("setDomain()", () => {
Expand Down Expand Up @@ -289,7 +302,7 @@ describe("Api class", () => {
.to.throw(`Expected string \`version\` to match \`${DeviceVersionRegex}\`, got \`${wrongFormat}\``);
});

it("should throw an error when using something other than a String as referer", () => {
it("should throw an error when using something other than a String as referrer", () => {
filterPrimitives([
"string",
"undefined",
Expand All @@ -303,23 +316,23 @@ describe("Api class", () => {
config.version,
set.value,
))
.to.throw(`Expected \`referer\` to be of type \`string\` but received type \`${set.type}\``);
.to.throw(`Expected \`referrer\` to be of type \`string\` but received type \`${set.type}\``);
});
});

it("should throw an error when using something other than a String as authorization", () => {
filterPrimitives([
"string",
"undefined", // Dont test for undefined, because authorization is optional and if we give undefined it will test for other params next
"undefined", // Don't test for undefined, because authorization is optional and if we give undefined it will test for other params next
]).forEach((set) => {
expect(() => config.api.subscribeDevice(
config.pushToken,
config.pushType,
true,
config.userAdditionalInformation,
config.type,
undefined,
undefined,
undefined,
undefined,
undefined,
config.version,
config.referer,
undefined,
set.value,
))
.to.throw(`Expected \`authorization\` to be of type \`string\` but received type \`${set.type}\``);
Expand Down Expand Up @@ -400,7 +413,7 @@ describe("Api class", () => {
});
});

it("should throw an error when using something other than a String as referer", () => {
it("should throw an error when using something other than a String as referrer", () => {
filterPrimitives([
"string",
"undefined",
Expand All @@ -409,16 +422,27 @@ describe("Api class", () => {
config.message,
set.value,
))
.to.throw(`Expected \`referer\` to be of type \`string\` but received type \`${set.type}\``);
.to.throw(`Expected \`referrer\` to be of type \`string\` but received type \`${set.type}\``);
});
});

it("should default referer to window.location.href", () => {
cy.visit("/");

config.api.sendMessage(config.message);

cy.wait("@postMessages").then((interception) => {
expect(JSON.parse(interception.request.body).referer)
.to.be.equal(window.location.href);
cy.location("href").then((href) => {
expect(JSON.parse(interception.request.body).referer)
.to.contain(href);

// There is an issue where the window.location.href will contain "iframe/xxx"
// due to how Cypress loads the chat, so we cannot check if the
// href equals the href we get here
// Instead we can only check if it begins with the href
// Error when using `.equal(href)`
// expected https://chat-dev.parley.nu:8181/__cypress/iframes/integration/api-class_spec.js to equal https://chat-dev.parley.nu:8181/
});
});
});

Expand Down
128 changes: 112 additions & 16 deletions cypress/integration/ui_spec.js
Expand Up @@ -69,7 +69,7 @@ describe("UI", () => {
.should("be.visible")
.find("[class^=error__]")
.should("be.visible")
.should("have.text", "The API request failed but the API did not return an error notification");
.should("have.text", "Something went wrong, please try again later");
});

it("should show the `serviceUnreachableNotification` error when the fetch request fails", () => {
Expand Down Expand Up @@ -382,6 +382,37 @@ describe("UI", () => {

cy.wait("@createDevice");
});
it("should clear the messages when switching accounts", () => {
const parleyConfig = {roomNumber: "0W4qcE5aXoKq9OzvHxj2"};
const testMessage = `test message before switching room numbers ${Date.now()}`;

cy.visit("/", {
onBeforeLoad: (win) => {
// eslint-disable-next-line no-param-reassign
win.parleySettings = parleyConfig;
},
});

cy.get("[id=app]").as("app");

clickOnLauncher();
sendMessage(testMessage);
findMessage(testMessage); // Wait until the server received the new message

// Change the account identification
const newAccountIdentification = "0cce5bfcdbf07978b269";
cy.window().then((win) => {
// eslint-disable-next-line no-param-reassign
win.parleySettings.roomNumber = newAccountIdentification;
});

cy.get("@app")
.find("[class^=wrapper__]")
.should("be.visible")
.find("[class^=body__]")
.should("be.visible")
.should("not.contain", testMessage);
});
});
describe("xIrisIdentification", () => {
it("should register a new device when switching identifications", () => {
Expand Down Expand Up @@ -525,25 +556,90 @@ describe("UI", () => {
// Test if it changes during runtime
const newWeekdays = [
[
"Monday", 8.00, 23.30,
"Monday", 0.00, 23.59,
],
[
"Tuesday", 0.00, 23.59,
],
[
"Wednesday", 0.00, 23.59,
],
[
"Thursday", 0.00, 23.59,
],
[
"Friday", 0.00, 23.59,
],
[
"Saturday", 0.00, 23.59,
],
[
"Sunday", 0.00, 23.59,
],
];

cy.window().then((win) => {
// eslint-disable-next-line no-param-reassign
win.parleySettings.weekdays = newWeekdays;
});

// Launcher should appear again because we
// are inside working hours
clickOnLauncher();
});
});
describe("format [day, start, end, true]", () => {
it("should show we are offline/online outside/inside working hours", () => {
const parleyConfig = {
weekdays: [ // closed every day
["Monday"],
["Tuesday"],
["Wednesday"],
["Thursday"],
["Friday"],
["Saturday"],
["Sunday"],
],
interface: {hideChatAfterBusinessHours: true},
};

cy.visit("/", {
onBeforeLoad: (win) => {
// eslint-disable-next-line no-param-reassign
win.parleySettings = parleyConfig;
},
});

cy.get("[id=app]").as("app");

// Launcher is not rendered because we are offline
// and outside working hours
cy.get("@app")
.get("[class^=launcher__]")
.should("not.exist");

// Test if it changes during runtime
const newWeekdays = [
[
"Monday", 0.00, 23.59, true,
],
[
"Tuesday", 8.00, 23.30,
"Tuesday", 0.00, 23.59, true,
],
[
"Wednesday", 8.00, 23.30,
"Wednesday", 0.00, 23.59, true,
],
[
"Thursday", 8.00, 23.30,
"Thursday", 0.00, 23.59, true,
],
[
"Friday", 8.00, 23.30,
"Friday", 0.00, 23.59, true,
],
[
"Saturday", 8.00, 23.30,
"Saturday", 0.00, 23.59, true,
],
[
"Sunday", 8.00, 23.30,
"Sunday", 0.00, 23.59, true,
],
];

Expand All @@ -557,7 +653,7 @@ describe("UI", () => {
clickOnLauncher();
});
});
describe("format [day, start, end, bool]", () => {
describe("format [day, start, end, false]", () => {
it("should show we are offline/online outside/inside working hours", () => {
const parleyConfig = {
weekdays: [ // closed every day
Expand Down Expand Up @@ -590,25 +686,25 @@ describe("UI", () => {
// Test if it changes during runtime
const newWeekdays = [
[
"Monday", 8.00, 23.30, true,
"Monday", 0.00, 0.00, false,
],
[
"Tuesday", 8.00, 23.30, true,
"Tuesday", 0.00, 0.00, false,
],
[
"Wednesday", 8.00, 23.30, true,
"Wednesday", 0.00, 0.00, false,
],
[
"Thursday", 8.00, 23.30, true,
"Thursday", 0.00, 0.00, false,
],
[
"Friday", 8.00, 23.30, true,
"Friday", 0.00, 0.00, false,
],
[
"Saturday", 8.00, 23.30, true,
"Saturday", 0.00, 0.00, false,
],
[
"Sunday", 8.00, 23.30, true,
"Sunday", 0.00, 0.00, false,
],
];

Expand Down

0 comments on commit 169fe9c

Please sign in to comment.