From eca0809d0cd6cdfb7cf14b71f7a2185129e8ac57 Mon Sep 17 00:00:00 2001
From: nmykhailets <94851929+nmykhailets@users.noreply.github.com>
Date: Tue, 8 Mar 2022 05:01:32 +0200
Subject: [PATCH] chore(samples): interactive tutorials code samples for
 write/rejoin/purge user events (#150)

Co-authored-by: tetiana-karasova <tetiana.karasova@gmail.com>
Co-authored-by: Karl Weinmeister <11586922+kweinmeister@users.noreply.github.com>
Co-authored-by: Benjamin E. Coe <bencoe@google.com>
---
 .../events/purge-user-events.js               | 73 ++++++++++++++++++
 .../events/rejoin-user-events.js              | 77 +++++++++++++++++++
 .../events/write-user-event.js                | 71 +++++++++++++++++
 .../test/purge-user-events.test.js            | 50 ++++++++++++
 .../test/rejoin-user-events.test.js           | 55 +++++++++++++
 .../test/write-user-event.test.js             | 63 +++++++++++++++
 6 files changed, 389 insertions(+)
 create mode 100644 retail/interactive-tutorials/events/purge-user-events.js
 create mode 100644 retail/interactive-tutorials/events/rejoin-user-events.js
 create mode 100644 retail/interactive-tutorials/events/write-user-event.js
 create mode 100644 retail/interactive-tutorials/test/purge-user-events.test.js
 create mode 100644 retail/interactive-tutorials/test/rejoin-user-events.test.js
 create mode 100644 retail/interactive-tutorials/test/write-user-event.test.js

diff --git a/retail/interactive-tutorials/events/purge-user-events.js b/retail/interactive-tutorials/events/purge-user-events.js
new file mode 100644
index 0000000000..e63c9f2c1a
--- /dev/null
+++ b/retail/interactive-tutorials/events/purge-user-events.js
@@ -0,0 +1,73 @@
+// Copyright 2022 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+'use strict';
+
+async function main() {
+  // [START retail_purge_user_events]
+
+  // Imports the Google Cloud client library.
+  const {UserEventServiceClient} = require('@google-cloud/retail').v2;
+  const utils = require('../setup/setup-cleanup');
+
+  const projectNumber = process.env['GCLOUD_PROJECT'];
+  const visitorId = 'test_visitor_id';
+
+  // Placement
+  const parent = `projects/${projectNumber}/locations/global/catalogs/default_catalog`;
+
+  // The filter string to specify the events to be deleted with a
+  // length limit of 5,000 characters.
+  const filter = `visitorId="${visitorId}"`; // TO CHECK ERROR HANDLING SET INVALID FILTER HERE
+
+  // Actually perform the purge.
+  const force = true;
+
+  // Instantiates a client.
+  const retailClient = new UserEventServiceClient();
+
+  const callPurgeUserEvents = async () => {
+    // Construct request
+    const request = {
+      parent,
+      filter,
+      force,
+    };
+
+    console.log('Purge request: ', request);
+
+    // Run request
+    const [operation] = await retailClient.purgeUserEvents(request);
+    console.log(
+      `Purge operation in progress.. Operation name: ${operation.name}`
+    );
+  };
+
+  // Create new event
+  const event = await utils.writeUserEvent(visitorId);
+  console.log(
+    `Created event ${event.eventType} with visitor id ${event.visitorId}`
+  );
+
+  // Purge events
+  await callPurgeUserEvents();
+  // [END retail_purge_user_events]
+}
+
+process.on('unhandledRejection', err => {
+  console.error(err.message);
+  process.exitCode = 1;
+});
+
+main();
diff --git a/retail/interactive-tutorials/events/rejoin-user-events.js b/retail/interactive-tutorials/events/rejoin-user-events.js
new file mode 100644
index 0000000000..82e73a54b5
--- /dev/null
+++ b/retail/interactive-tutorials/events/rejoin-user-events.js
@@ -0,0 +1,77 @@
+// Copyright 2022 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+'use strict';
+
+async function main() {
+  // [START retail_rejoin_user_event]
+
+  // Imports the Google Cloud client library.
+  const {UserEventServiceClient} = require('@google-cloud/retail').v2;
+  const utils = require('../setup/setup-cleanup');
+
+  const projectNumber = process.env['GCLOUD_PROJECT'];
+  const visitorId = 'test_visitor_id';
+
+  // Placement
+  const parent = `projects/${projectNumber}/locations/global/catalogs/default_catalog`; // TO CHECK ERROR HANDLING PASTE THE INVALID CATALOG NAME HERE
+
+  const UserEventRejoinScope = {
+    USER_EVENT_REJOIN_SCOPE_UNSPECIFIED: 0,
+    JOINED_EVENTS: 1,
+    UNJOINED_EVENTS: 2,
+  };
+  // The type of the user event rejoin to define the scope and range of the user
+  // events to be rejoined with the latest product catalog
+  const userEventRejoinScope = UserEventRejoinScope.UNJOINED_EVENTS;
+
+  // Instantiates a client.
+  const retailClient = new UserEventServiceClient();
+
+  const callRejoinUserEvents = async () => {
+    // Construct request
+    const request = {
+      parent,
+      userEventRejoinScope,
+    };
+
+    console.log('Rejoin request: ', request);
+
+    // Run request
+    const [operation] = await retailClient.rejoinUserEvents(request);
+    console.log(
+      `Rejoin operation in progress.. Operation name: ${operation.name}`
+    );
+  };
+
+  // Create new event
+  const event = await utils.writeUserEvent(visitorId);
+  console.log(
+    `Created event ${event.eventType} with visitor id ${event.visitorId}`
+  );
+
+  // Rejoin events
+  await callRejoinUserEvents();
+
+  // Purge events
+  utils.purgeUserEvents(parent, visitorId);
+  // [END retail_rejoin_user_event]
+}
+
+process.on('unhandledRejection', err => {
+  console.error(err.message);
+  process.exitCode = 1;
+});
+
+main();
diff --git a/retail/interactive-tutorials/events/write-user-event.js b/retail/interactive-tutorials/events/write-user-event.js
new file mode 100644
index 0000000000..6763abbde8
--- /dev/null
+++ b/retail/interactive-tutorials/events/write-user-event.js
@@ -0,0 +1,71 @@
+// Copyright 2022 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+'use strict';
+
+async function main() {
+  // [START retail_write_user_event]
+
+  // Imports the Google Cloud client library.
+  const {UserEventServiceClient} = require('@google-cloud/retail').v2;
+  const utils = require('../setup/setup-cleanup');
+
+  const projectNumber = process.env['GCLOUD_PROJECT'];
+  const visitorId = 'test_visitor_id';
+
+  // Placement
+  const parent = `projects/${projectNumber}/locations/global/catalogs/default_catalog`; // TO CHECK ERROR HANDLING PASTE THE INVALID CATALOG NAME HERE
+
+  // User event to write
+  const userEvent = {
+    eventType: 'home-page-view',
+    visitorId,
+    eventTime: {
+      seconds: Math.round(Date.now() / 1000),
+    },
+  };
+
+  // Instantiates a client.
+  const retailClient = new UserEventServiceClient();
+
+  const callWriteUserEvent = async () => {
+    // Construct request
+    const request = {
+      userEvent,
+      parent,
+    };
+
+    console.log('Write request: ', request);
+
+    // Run request
+    const response = await retailClient.writeUserEvent(request);
+    console.log(`Operation result: ${JSON.stringify(response[0])}`);
+  };
+
+  // Create new user event
+  console.log('Start to write user event');
+  await callWriteUserEvent();
+  console.log('Write operation finished');
+
+  // Purge user events by visitor id
+  await utils.purgeUserEvents(parent, visitorId);
+  // [END retail_write_user_event]
+}
+
+process.on('unhandledRejection', err => {
+  console.error(err.message);
+  process.exitCode = 1;
+});
+
+main();
diff --git a/retail/interactive-tutorials/test/purge-user-events.test.js b/retail/interactive-tutorials/test/purge-user-events.test.js
new file mode 100644
index 0000000000..71ba59fea4
--- /dev/null
+++ b/retail/interactive-tutorials/test/purge-user-events.test.js
@@ -0,0 +1,50 @@
+// Copyright 2022 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+'use strict';
+
+const path = require('path');
+const cp = require('child_process');
+const {before, describe, it} = require('mocha');
+const {assert} = require('chai');
+
+const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'});
+
+const cwd = path.join(__dirname, '..');
+
+describe('Purge user events', () => {
+  const eventType = 'detail-page-view';
+  const visitorId = 'test_visitor_id';
+  let stdout;
+
+  before(async () => {
+    stdout = execSync(
+      'node interactive-tutorials/events/purge-user-events.js',
+      {cwd}
+    );
+  });
+
+  it('should check that new event already created', () => {
+    const regex = new RegExp(
+      `Created event ${eventType} with visitor id ${visitorId}`,
+      'g'
+    );
+    assert.match(stdout, regex);
+  });
+
+  it('should check that purge operation started', () => {
+    const regex = new RegExp('Purge operation in progress', 'g');
+    assert.match(stdout, regex);
+  });
+});
diff --git a/retail/interactive-tutorials/test/rejoin-user-events.test.js b/retail/interactive-tutorials/test/rejoin-user-events.test.js
new file mode 100644
index 0000000000..2a8e701836
--- /dev/null
+++ b/retail/interactive-tutorials/test/rejoin-user-events.test.js
@@ -0,0 +1,55 @@
+// Copyright 2022 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+'use strict';
+
+const path = require('path');
+const cp = require('child_process');
+const {before, describe, it} = require('mocha');
+const {assert} = require('chai');
+
+const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'});
+
+const cwd = path.join(__dirname, '..');
+
+describe('Rejoin user events', () => {
+  const eventType = 'detail-page-view';
+  const visitorId = 'test_visitor_id';
+  let stdout;
+
+  before(async () => {
+    stdout = execSync(
+      'node interactive-tutorials/events/rejoin-user-events.js',
+      {cwd}
+    );
+  });
+
+  it('should check that new event already created', () => {
+    const regex = new RegExp(
+      `Created event ${eventType} with visitor id ${visitorId}`,
+      'g'
+    );
+    assert.match(stdout, regex);
+  });
+
+  it('should check that rejoin operation started', () => {
+    const regex = new RegExp('Rejoin operation in progress', 'g');
+    assert.match(stdout, regex);
+  });
+
+  it('should check that purge operation started', () => {
+    const regex = new RegExp('Purge operation in progress', 'g');
+    assert.match(stdout, regex);
+  });
+});
diff --git a/retail/interactive-tutorials/test/write-user-event.test.js b/retail/interactive-tutorials/test/write-user-event.test.js
new file mode 100644
index 0000000000..ac982ba75e
--- /dev/null
+++ b/retail/interactive-tutorials/test/write-user-event.test.js
@@ -0,0 +1,63 @@
+// Copyright 2022 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+'use strict';
+
+const path = require('path');
+const cp = require('child_process');
+const {before, describe, it} = require('mocha');
+const {assert, expect} = require('chai');
+
+const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'});
+
+const cwd = path.join(__dirname, '..');
+
+describe('Write user event', () => {
+  const eventType = 'home-page-view';
+  const visitorId = 'test_visitor_id';
+  let stdout;
+
+  before(async () => {
+    stdout = execSync('node interactive-tutorials/events/write-user-event.js', {
+      cwd,
+    });
+  });
+
+  it('should check that write operation started', () => {
+    const regex = new RegExp('Start to write user event', 'g');
+    assert.match(stdout, regex);
+  });
+
+  it('should check that new event created correctly', () => {
+    const regex = new RegExp('Operation result: .*\\n', 'g');
+    assert.match(stdout, regex);
+    const string = stdout
+      .match(regex)
+      .toString()
+      .replace('Operation result: ', '');
+    const event = JSON.parse(string);
+    expect(event.eventType).to.be.equal(eventType);
+    expect(event.visitorId).to.be.equal(visitorId);
+  });
+
+  it('should check that write operation finished', () => {
+    const regex = new RegExp('Write operation finished', 'g');
+    assert.match(stdout, regex);
+  });
+
+  it('should check that purge operation started', () => {
+    const regex = new RegExp('Purge operation in progress', 'g');
+    assert.match(stdout, regex);
+  });
+});