From c70edc65bcf0d9a02b67d15cfe43318459e2685a Mon Sep 17 00:00:00 2001 From: nmykhailets <94851929+nmykhailets@users.noreply.github.com> Date: Tue, 8 Mar 2022 17:54:57 +0200 Subject: [PATCH] chore(samples): interactive tutorials code samples for CRUD products (#149) --- .../product/add-fulfillment-places.js | 98 +++++++++++ .../product/create-product.js | 83 ++++++++++ .../product/crud-product.js | 155 ++++++++++++++++++ .../product/delete-product.js | 58 +++++++ .../product/get-product.js | 65 ++++++++ .../product/get-products-list.js | 56 +++++++ .../product/remove-fulfillment-places.js | 93 +++++++++++ .../product/set-inventory.js | 118 +++++++++++++ .../product/update-product.js | 91 ++++++++++ .../test/add-fulfillment.test.js | 95 +++++++++++ .../test/create-product.test.js | 63 +++++++ .../test/crud-product.test.js | 116 +++++++++++++ .../test/delete-product.test.js | 63 +++++++ .../test/get-product.test.js | 70 ++++++++ .../test/get-products-list.test.js | 43 +++++ .../test/remove-fulfillment.test.js | 98 +++++++++++ .../test/set-inventory.test.js | 151 +++++++++++++++++ .../test/update-product.test.js | 105 ++++++++++++ 18 files changed, 1621 insertions(+) create mode 100644 retail/interactive-tutorials/product/add-fulfillment-places.js create mode 100644 retail/interactive-tutorials/product/create-product.js create mode 100644 retail/interactive-tutorials/product/crud-product.js create mode 100644 retail/interactive-tutorials/product/delete-product.js create mode 100644 retail/interactive-tutorials/product/get-product.js create mode 100644 retail/interactive-tutorials/product/get-products-list.js create mode 100644 retail/interactive-tutorials/product/remove-fulfillment-places.js create mode 100644 retail/interactive-tutorials/product/set-inventory.js create mode 100644 retail/interactive-tutorials/product/update-product.js create mode 100644 retail/interactive-tutorials/test/add-fulfillment.test.js create mode 100644 retail/interactive-tutorials/test/create-product.test.js create mode 100644 retail/interactive-tutorials/test/crud-product.test.js create mode 100644 retail/interactive-tutorials/test/delete-product.test.js create mode 100644 retail/interactive-tutorials/test/get-product.test.js create mode 100644 retail/interactive-tutorials/test/get-products-list.test.js create mode 100644 retail/interactive-tutorials/test/remove-fulfillment.test.js create mode 100644 retail/interactive-tutorials/test/set-inventory.test.js create mode 100644 retail/interactive-tutorials/test/update-product.test.js diff --git a/retail/interactive-tutorials/product/add-fulfillment-places.js b/retail/interactive-tutorials/product/add-fulfillment-places.js new file mode 100644 index 0000000000..9612d1c829 --- /dev/null +++ b/retail/interactive-tutorials/product/add-fulfillment-places.js @@ -0,0 +1,98 @@ +// 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(generatedProductId) { + // [START retail_add_remove_fulfillment_places] + + // Imports the Google Cloud client library. + const {ProductServiceClient} = require('@google-cloud/retail').v2; + const utils = require('../setup/setup-cleanup'); + + const projectNumber = process.env['GCLOUD_PROJECT']; + + // Create product + const createdProduct = await utils.createProduct( + projectNumber, + generatedProductId + ); + + // Full resource name of Product + const product = createdProduct.name; + + // The fulfillment type, including commonly used types (such as + // pickup in store and same day delivery), and custom types. + const type = 'same-day-delivery'; + + // The IDs for this type, such as the store IDs for "pickup-in-store" or the region IDs for + // "same-day-delivery" to be added for this type. + const placeIds = ['store1', 'store2', 'store3']; + + // The time when the fulfillment updates are issued, used to prevent + // out-of-order updates on fulfillment information. + const addTime = { + seconds: Math.round(Date.now() / 1000), + }; + + //If set to true, and the product is not found, the fulfillment information will still be processed and retained for + // at most 1 day and processed once the product is created + const allowMissing = true; + + // Instantiates a client. + const retailClient = new ProductServiceClient(); + + const calladdFulfillmentPlaces = async () => { + // Construct request + const request = { + product, + type, + placeIds, + addTime, + allowMissing, + }; + + console.log('Add fulfillment request:', request); + + // Run request + await retailClient.addFulfillmentPlaces(request); + + console.log('Waiting to complete add operation..'); + }; + + // Add fulfillment places with current time + console.log('Start add fulfillment'); + await calladdFulfillmentPlaces(); + await utils.delay(180000); + + //Get product + const response = await utils.getProduct(product); + console.log( + 'Updated product with current time: ', + JSON.stringify(response[0]) + ); + console.log('Add fulfillment finished'); + + // Delete product + await utils.deleteProduct(product); + console.log(`Product ${createdProduct.id} deleted`); + // [END retail_add_remove_fulfillment_places] +} + +process.on('unhandledRejection', err => { + console.error('ERROR', err.message); + process.exitCode = 1; +}); + +main(...process.argv.slice(2)); diff --git a/retail/interactive-tutorials/product/create-product.js b/retail/interactive-tutorials/product/create-product.js new file mode 100644 index 0000000000..a385af3c18 --- /dev/null +++ b/retail/interactive-tutorials/product/create-product.js @@ -0,0 +1,83 @@ +// 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(generatedProductId) { + // [START retail_create_product] + + // Imports the Google Cloud client library. + const {ProductServiceClient} = require('@google-cloud/retail').v2; + const utils = require('../setup/setup-cleanup'); + + const projectNumber = process.env['GCLOUD_PROJECT']; + + // The parent catalog resource name + const parent = `projects/${projectNumber}/locations/global/catalogs/default_catalog/branches/default_branch`; + + // The ID to use for the product + const productId = generatedProductId + ? generatedProductId + : Math.random().toString(36).slice(2).toUpperCase(); + + // The product to create. + const product = { + title: 'Nest Mini', + type: 'PRIMARY', + categories: ['Speakers and displays'], + brands: ['Google'], + priceInfo: { + price: 30.0, + originalPrice: 35.5, + currencyCode: 'USD', + }, + availability: 'IN_STOCK', + }; + + // Instantiates a client. + const retailClient = new ProductServiceClient(); + + const callCreateProduct = async () => { + // Construct request + const request = { + parent, + product, + productId, + }; + console.log('Create product request:', request); + + // Run request + const response = await retailClient.createProduct(request); + console.log('Created product:', response); + return response[0]; + }; + + // Create product + console.log('Start to create the product'); + const createdProduct = await callCreateProduct(); + console.log(`Product ${createdProduct.id} creation ended`); + + // Delete product + await utils.deleteProduct(createdProduct.name); + console.log(`Product ${createdProduct.id} deleted`); + + // [END retail_create_product] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); + +main(...process.argv.slice(2)); diff --git a/retail/interactive-tutorials/product/crud-product.js b/retail/interactive-tutorials/product/crud-product.js new file mode 100644 index 0000000000..a4c3ea1ee8 --- /dev/null +++ b/retail/interactive-tutorials/product/crud-product.js @@ -0,0 +1,155 @@ +// 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(generatedProductId) { + // [START retail_crud_product] + + // Imports the Google Cloud client library. + const {ProductServiceClient} = require('@google-cloud/retail').v2; + + const projectNumber = process.env['GCLOUD_PROJECT']; + + // The parent catalog resource name + const parent = `projects/${projectNumber}/locations/global/catalogs/default_catalog/branches/default_branch`; + + // The ID to use for the product + const productId = generatedProductId + ? generatedProductId + : Math.random().toString(36).slice(2).toUpperCase(); + + // Full resource name of Product + const name = `${parent}/products/${productId}`; + + // The product to create. + const productForCreate = { + title: 'Nest Mini', + type: 'PRIMARY', + categories: ['Speakers and displays'], + brands: ['Google'], + priceInfo: { + price: 30.0, + originalPrice: 35.5, + currencyCode: 'USD', + }, + availability: 'IN_STOCK', + }; + + // The product to update. + const productForUpdate = { + productId, + name, + title: 'Updated Nest Mini', + type: 'PRIMARY', + categories: ['Updated Speakers and displays'], + brands: ['Updated Google'], + priceInfo: { + price: 20.0, + originalPrice: 25.5, + currencyCode: 'EUR', + }, + availability: 'OUT_OF_STOCK', + }; + + // Instantiates a client. + const retailClient = new ProductServiceClient(); + + const callCreateProduct = async () => { + // Construct request + const request = { + parent, + product: productForCreate, + productId, + }; + console.log('Create product request:', request); + + // Run request + const response = await retailClient.createProduct(request); + console.log('Created product:', response); + return response[0]; + }; + + const callGetProduct = async () => { + // Construct request + const request = { + name, + }; + console.log('Get product request:', request); + + // Run request + const response = await retailClient.getProduct(request); + console.log('Get product response:', response); + + return response[0]; + }; + + const callUpdateProduct = async () => { + // Construct request + const request = { + product: productForUpdate, + }; + console.log('Update product request:', request); + + // Run request + const response = await retailClient.updateProduct(request); + console.log('Updated product:', response); + + return response[0]; + }; + + const callDeleteProduct = async () => { + // Construct request + const request = { + name, + }; + console.log('Delete product request:', request); + + // Run request + await retailClient.deleteProduct(request); + }; + + console.log('Start CRUD product'); + // Create product + console.log('Start to create the product'); + const createdProduct = await callCreateProduct(); + console.log(`Product ${createdProduct.id} creation finished`); + + // Get product + console.log('Start product get operation'); + const foundProduct = await callGetProduct(); + console.log(`Product ${foundProduct.id} get operation finished`); + + // Update product + console.log('Start product update'); + const updatedProduct = await callUpdateProduct(); + console.log( + `Product ${updatedProduct.id} update finished: `, + JSON.stringify(updatedProduct) + ); + + // Delete product + console.log('Start deleting the product'); + await callDeleteProduct(); + console.log(`Product ${createdProduct.id} deleted`); + console.log('CRUD product finished'); + // [END retail_crud_product] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); + +main(...process.argv.slice(2)); diff --git a/retail/interactive-tutorials/product/delete-product.js b/retail/interactive-tutorials/product/delete-product.js new file mode 100644 index 0000000000..daee6c17ef --- /dev/null +++ b/retail/interactive-tutorials/product/delete-product.js @@ -0,0 +1,58 @@ +// 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(generatedProductId) { + // [START retail_delete_product] + + // Imports the Google Cloud client library. + const {ProductServiceClient} = require('@google-cloud/retail').v2; + const utils = require('../setup/setup-cleanup'); + + const projectNumber = process.env['GCLOUD_PROJECT']; + + // Create product + const product = await utils.createProduct(projectNumber, generatedProductId); + + // Full resource name of Product + const name = product.name; + + // Instantiates a client. + const retailClient = new ProductServiceClient(); + + const callDeleteProduct = async () => { + // Construct request + const request = { + name, + }; + console.log('Delete product request:', request); + + // Run request + await retailClient.deleteProduct(request); + }; + + // Delete product + console.log('Start deleting the product'); + await callDeleteProduct(); + console.log(`Product ${product.id} deleted`); + // [END retail_delete_product] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); + +main(...process.argv.slice(2)); diff --git a/retail/interactive-tutorials/product/get-product.js b/retail/interactive-tutorials/product/get-product.js new file mode 100644 index 0000000000..ef015d8ece --- /dev/null +++ b/retail/interactive-tutorials/product/get-product.js @@ -0,0 +1,65 @@ +// 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(generatedProductId) { + // [START retail_get_product] + + // Imports the Google Cloud client library. + const {ProductServiceClient} = require('@google-cloud/retail').v2; + const utils = require('../setup/setup-cleanup'); + + const projectNumber = process.env['GCLOUD_PROJECT']; + + // Create product + const product = await utils.createProduct(projectNumber, generatedProductId); + + // Full resource name of Product + const name = product.name; + + // Instantiates a client. + const retailClient = new ProductServiceClient(); + + const callGetProduct = async () => { + // Construct request + const request = { + name, + }; + console.log('Get product request:', request); + + // Run request + const response = await retailClient.getProduct(request); + console.log('Get product response:', response); + + return response[0]; + }; + + // Get product + console.log('Start product get operation'); + const foundProduct = await callGetProduct(); + console.log(`Product ${foundProduct.id} get operation finished`); + + // Delete product + await utils.deleteProduct(name); + console.log(`Product ${foundProduct.id} deleted`); + // [END retail_get_product] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); + +main(...process.argv.slice(2)); diff --git a/retail/interactive-tutorials/product/get-products-list.js b/retail/interactive-tutorials/product/get-products-list.js new file mode 100644 index 0000000000..cffc146512 --- /dev/null +++ b/retail/interactive-tutorials/product/get-products-list.js @@ -0,0 +1,56 @@ +// 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_get_products_list] + + // Imports the Google Cloud client library. + const {ProductServiceClient} = require('@google-cloud/retail').v2; + + const projectNumber = process.env['GCLOUD_PROJECT']; + + // Placement + const parent = `projects/${projectNumber}/locations/global/catalogs/default_catalog/branches/default_branch`; + + // Instantiates a client. + const retailClient = new ProductServiceClient(); + + async function callListProducts() { + console.log('Start get products list'); + // Construct request + const request = { + parent, + }; + console.log('List of products request:', request); + + // Run request + const iterable = await retailClient.listProductsAsync(request); + for await (const response of iterable) { + console.log(response); + } + console.log('Get products list finished'); + } + + callListProducts(); + // [END retail_get_products_list] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); + +main(); diff --git a/retail/interactive-tutorials/product/remove-fulfillment-places.js b/retail/interactive-tutorials/product/remove-fulfillment-places.js new file mode 100644 index 0000000000..3e5ce00df4 --- /dev/null +++ b/retail/interactive-tutorials/product/remove-fulfillment-places.js @@ -0,0 +1,93 @@ +// 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(generatedProductId) { + // [START retail_remove_fulfillment_places] + + // Imports the Google Cloud client library. + const {ProductServiceClient} = require('@google-cloud/retail').v2; + const utils = require('../setup/setup-cleanup'); + + const projectNumber = process.env['GCLOUD_PROJECT']; + + // Create product + const createdProduct = await utils.createProduct( + projectNumber, + generatedProductId, + true + ); + + // Full resource name of Product + const product = createdProduct.name; + + // The fulfillment type, including commonly used types (such as + // pickup in store and same day delivery), and custom types. + const type = 'same-day-delivery'; + + // The IDs for this type, such as the store IDs for "pickup-in-store" or the region IDs for + // "same-day-delivery" to be added for this type. + const placeIds = ['store1']; + + // The time when the fulfillment updates are issued, used to prevent + // out-of-order updates on fulfillment information. + const removeTime = { + seconds: Math.round(Date.now() / 1000), + }; + + // Instantiates a client. + const retailClient = new ProductServiceClient(); + + const callRemoveFulfillmentPlaces = async () => { + // Construct request + const request = { + product, + type, + placeIds, + removeTime, + }; + + console.log('Remove fulfillment request:', request); + // Run request + await retailClient.removeFulfillmentPlaces(request); + + console.log('Waiting to complete remove operation..'); + }; + + // Remove fulfillment places with current time + console.log('Start remove fulfillment'); + await callRemoveFulfillmentPlaces(); + await utils.delay(180000); + + //Get product + const response = await utils.getProduct(product); + console.log( + 'Updated product with current time: ', + JSON.stringify(response[0]) + ); + console.log('Remove fulfillment finished'); + + // Delete product + await utils.deleteProduct(product); + console.log(`Product ${createdProduct.id} deleted`); + // [END retail_remove_fulfillment_places] +} + +process.on('unhandledRejection', err => { + console.error('ERROR', err.message); + process.exitCode = 1; +}); + +main(...process.argv.slice(2)); diff --git a/retail/interactive-tutorials/product/set-inventory.js b/retail/interactive-tutorials/product/set-inventory.js new file mode 100644 index 0000000000..6d8586c592 --- /dev/null +++ b/retail/interactive-tutorials/product/set-inventory.js @@ -0,0 +1,118 @@ +// 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(generatedProductId) { + // [START retail_set_inventory] + + // Imports the Google Cloud client library. + const {ProductServiceClient} = require('@google-cloud/retail').v2; + const utils = require('../setup/setup-cleanup'); + + const projectNumber = process.env['GCLOUD_PROJECT']; + + // Create product + const createdProduct = await utils.createProduct( + projectNumber, + generatedProductId + ); + + // The inventory information to update + const product = { + id: createdProduct.id, + name: createdProduct.name, + priceInfo: { + price: 15.0, + originalPrice: 20.0, + cost: 8.0, + currencyCode: 'USD', + }, + fulfillmentInfo: [ + { + type: 'same-day-delivery', + placeIds: ['store3', 'store4'], + }, + ], + availableQuantity: { + value: 2, + }, + availability: 'IN_STOCK', + }; + + // The time when the request is issued, used to prevent + // out-of-order updates on inventory fields with the last update time recorded. + let setTime = { + seconds: Math.round(Date.now() / 1000), + }; + + // If set to true, and the product with name is not found, the + // inventory update will still be processed and retained for at most 1 day until the product is created + const allowMissing = true; + + // Instantiates a client. + const retailClient = new ProductServiceClient(); + + const callSetInventory = async () => { + // Construct request + const request = { + inventory: product, + setTime, + allowMissing, + }; + console.log('Set inventory request:', request); + + // Run request + await retailClient.setInventory(request); + console.log('Waiting to complete set inventory operation..'); + }; + + // Set inventory with current time + console.log('Start set inventory'); + await callSetInventory(); + await utils.delay(180000); + + // Get product + let changedProduct = await utils.getProduct(createdProduct.name); + console.log( + `Updated product ${createdProduct.id} with current time: `, + JSON.stringify(changedProduct[0]) + ); + + // Set inventory with outdated time + product.priceInfo.price = 20.0; + setTime = {seconds: Math.round(Date.now() / 1000) - 86400}; + await callSetInventory(); + await utils.delay(180000); + + // Get product + changedProduct = await utils.getProduct(createdProduct.name); + console.log( + `Updated product ${createdProduct.id} with outdated time: `, + JSON.stringify(changedProduct[0]) + ); + console.log('Set inventory finished'); + + // Delete product + await utils.deleteProduct(createdProduct.name); + console.log(`Product ${createdProduct.id} deleted`); + // [END retail_set_inventory] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); + +main(...process.argv.slice(2)); diff --git a/retail/interactive-tutorials/product/update-product.js b/retail/interactive-tutorials/product/update-product.js new file mode 100644 index 0000000000..30a2da2a1c --- /dev/null +++ b/retail/interactive-tutorials/product/update-product.js @@ -0,0 +1,91 @@ +// 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(generatedProductId) { + // [START retail_update_product] + + // Imports the Google Cloud client library. + const {ProductServiceClient} = require('@google-cloud/retail').v2; + const utils = require('../setup/setup-cleanup'); + + const projectNumber = process.env['GCLOUD_PROJECT']; + + // Create product + const createdProduct = await utils.createProduct( + projectNumber, + generatedProductId + ); + + // The ID to use for the product + const productId = createdProduct.id; + + // The parent catalog resource name + const name = createdProduct.name; + + // The product to update. + const product = { + productId, + name, + title: 'Updated Nest Mini', + type: 'PRIMARY', + categories: ['Updated Speakers and displays'], + brands: ['Updated Google'], + priceInfo: { + price: 20.0, + originalPrice: 25.5, + currencyCode: 'EUR', + }, + availability: 'OUT_OF_STOCK', + }; + + // Instantiates a client. + const retailClient = new ProductServiceClient(); + + const callUpdateProduct = async () => { + // Construct request + const request = { + product, + }; + console.log('Update product request:', request); + + // Run request + const response = await retailClient.updateProduct(request); + console.log('Updated product:', response); + + return response[0]; + }; + + // Update product + console.log('Start product update'); + const updatedProduct = await callUpdateProduct(); + console.log( + `Product ${updatedProduct.id} update finished: `, + JSON.stringify(updatedProduct) + ); + + // Delete product + await utils.deleteProduct(updatedProduct.name); + console.log(`Product ${updatedProduct.id} deleted`); + + // [END retail_update_product] +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); + +main(...process.argv.slice(2)); diff --git a/retail/interactive-tutorials/test/add-fulfillment.test.js b/retail/interactive-tutorials/test/add-fulfillment.test.js new file mode 100644 index 0000000000..080c922d8f --- /dev/null +++ b/retail/interactive-tutorials/test/add-fulfillment.test.js @@ -0,0 +1,95 @@ +// 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, after} = require('mocha'); +const {ProductServiceClient} = require('@google-cloud/retail'); +const {assert, expect} = require('chai'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); + +const cwd = path.join(__dirname, '..'); + +describe('Add fulfillment', () => { + const retailClient = new ProductServiceClient(); + const productId = Math.random().toString(36).slice(2).toUpperCase(); + const projectNumber = process.env['GCLOUD_PROJECT']; + const name = `projects/${projectNumber}/locations/global/catalogs/default_catalog/branches/default_branch/products/${productId}`; + + let stdout; + + before(async () => { + stdout = execSync( + `node interactive-tutorials/product/add-fulfillment-places.js ${productId}`, + { + cwd, + } + ); + }); + + it('should check that product created', () => { + const regex = new RegExp(`Product ${productId} created`, 'g'); + assert.match(stdout, regex); + }); + + it('should check that add fulfillment started', () => { + assert.match(stdout, /Start add fulfillment/); + }); + + it('should check that add fulfillment finished', () => { + assert.match(stdout, /Add fulfillment finished/); + }); + + it('should check that product updated correctly', async () => { + const regex = new RegExp('Updated product with current time: .*\\n', 'g'); + assert.match(stdout, regex); + const string = stdout + .match(regex) + .toString() + .replace('Updated product with current time: ', ''); + const updatedProduct = JSON.parse(string); + + expect(updatedProduct).to.be.an('object'); + expect(updatedProduct.fulfillmentInfo).to.be.an('array'); + expect( + updatedProduct.fulfillmentInfo.length, + 'Fulfillment array is empty' + ).to.equal(1); + + const item = updatedProduct.fulfillmentInfo[0]; + expect(item).to.be.an('object'); + expect(item).to.have.all.keys('type', 'placeIds'); + expect(item.type).to.equal('same-day-delivery'); + expect(item.placeIds) + .to.be.an('array') + .that.includes('store1', 'store2', 'store3'); + }); + + it('should check that product deleted', async () => { + const regex = new RegExp(`Product ${productId} deleted`, 'g'); + assert.match(stdout, regex); + }); + + after(async () => { + try { + const product = await retailClient.getProduct({name: name}); + expect(product, 'The product not deleted').to.be.undefined; + } catch (err) { + expect(err, 'Bad error code').to.include({code: 5}); + } + }); +}); diff --git a/retail/interactive-tutorials/test/create-product.test.js b/retail/interactive-tutorials/test/create-product.test.js new file mode 100644 index 0000000000..060cdc07af --- /dev/null +++ b/retail/interactive-tutorials/test/create-product.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, after} = require('mocha'); +const {ProductServiceClient} = require('@google-cloud/retail'); +const {assert, expect} = require('chai'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); + +const cwd = path.join(__dirname, '..'); + +describe('Create product', () => { + const retailClient = new ProductServiceClient(); + const productId = Math.random().toString(36).slice(2).toUpperCase(); + const projectNumber = process.env['GCLOUD_PROJECT']; + const name = `projects/${projectNumber}/locations/global/catalogs/default_catalog/branches/default_branch/products/${productId}`; + let stdout; + + before(async () => { + stdout = execSync( + `node interactive-tutorials/product/create-product.js ${productId}`, + {cwd} + ); + }); + + it('should check that product creation started', () => { + assert.match(stdout, /Start to create the product/); + }); + + it('should check that product created', () => { + const regex = new RegExp(`Product ${productId} creation ended`, 'g'); + assert.match(stdout, regex); + }); + + it('should check that product deleted', async () => { + const regex = new RegExp(`Product ${productId} deleted`, 'g'); + assert.match(stdout, regex); + }); + + after(async () => { + try { + const product = await retailClient.getProduct({name: name}); + expect(product, 'The product not deleted').to.be.undefined; + } catch (err) { + expect(err, 'Bad error code').to.include({code: 5}); + } + }); +}); diff --git a/retail/interactive-tutorials/test/crud-product.test.js b/retail/interactive-tutorials/test/crud-product.test.js new file mode 100644 index 0000000000..b7f83bf8ae --- /dev/null +++ b/retail/interactive-tutorials/test/crud-product.test.js @@ -0,0 +1,116 @@ +// 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, after} = require('mocha'); +const {ProductServiceClient} = require('@google-cloud/retail'); +const {assert, expect} = require('chai'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); +const cwd = path.join(__dirname, '..'); + +describe('CRUD product', () => { + const retailClient = new ProductServiceClient(); + const productId = Math.random().toString(36).slice(2).toUpperCase(); + const projectNumber = process.env['GCLOUD_PROJECT']; + const name = `projects/${projectNumber}/locations/global/catalogs/default_catalog/branches/default_branch/products/${productId}`; + const product = { + productId, + name, + title: 'Updated Nest Mini', + type: 'PRIMARY', + categories: ['Updated Speakers and displays'], + brands: ['Updated Google'], + priceInfo: { + price: 20.0, + originalPrice: 25.5, + currencyCode: 'EUR', + }, + availability: 'OUT_OF_STOCK', + }; + let stdout; + + before(async () => { + stdout = execSync( + `node interactive-tutorials/product/crud-product.js ${productId}`, + {cwd} + ); + }); + + it('should check that product CRUD operation started', () => { + assert.match(stdout, /Start CRUD product/); + }); + + it('should check that product created', () => { + const regex = new RegExp(`Product ${productId} creation finished`, 'g'); + assert.match(stdout, regex); + }); + + it('should check that product get operation finished', () => { + const regex = new RegExp( + `Product ${productId} get operation finished`, + 'g' + ); + assert.match(stdout, regex); + }); + + it('should check that product update finished', async () => { + const regex = new RegExp( + `Product ${productId} update finished: .*\\n`, + 'g' + ); + assert.match(stdout, regex); + const string = stdout + .match(regex) + .toString() + .replace(`Product ${productId} update finished: `, ''); + const updatedProduct = JSON.parse(string); + expect(updatedProduct).to.be.an('object'); + expect(updatedProduct).to.have.deep.property( + 'title', + product.title, + 'type', + product.type, + 'categories', + product.categories, + 'brands', + product.brands, + 'priceInfo', + product.priceInfo, + 'availability', + product.availability + ); + }); + + it('should check that product deleted', async () => { + const regex = new RegExp(`Product ${productId} deleted`, 'g'); + assert.match(stdout, regex); + }); + + it('should check that product CRUD operation finished', () => { + assert.match(stdout, /CRUD product finished/); + }); + + after(async () => { + try { + const product = await retailClient.getProduct({name: name}); + expect(product, 'The product not deleted').to.be.undefined; + } catch (err) { + expect(err, 'Bad error code').to.include({code: 5}); + } + }); +}); diff --git a/retail/interactive-tutorials/test/delete-product.test.js b/retail/interactive-tutorials/test/delete-product.test.js new file mode 100644 index 0000000000..18b8d9dbda --- /dev/null +++ b/retail/interactive-tutorials/test/delete-product.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, after} = require('mocha'); +const {ProductServiceClient} = require('@google-cloud/retail'); +const {assert, expect} = require('chai'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); + +const cwd = path.join(__dirname, '..'); + +describe('Delete product', () => { + const retailClient = new ProductServiceClient(); + const productId = Math.random().toString(36).slice(2).toUpperCase(); + const projectNumber = process.env['GCLOUD_PROJECT']; + const name = `projects/${projectNumber}/locations/global/catalogs/default_catalog/branches/default_branch/products/${productId}`; + let stdout; + + before(async () => { + stdout = execSync( + `node interactive-tutorials/product/delete-product.js ${productId}`, + {cwd} + ); + }); + + it('should check that product created', () => { + const regex = new RegExp(`Product ${productId} created`, 'g'); + assert.match(stdout, regex); + }); + + it('should check that product deletion started', () => { + assert.match(stdout, /Start deleting the product/); + }); + + it('should check that product deleted', async () => { + const regex = new RegExp(`Product ${productId} deleted`, 'g'); + assert.match(stdout, regex); + }); + + after(async () => { + try { + const product = await retailClient.getProduct({name: name}); + expect(product, 'The product not deleted').to.be.undefined; + } catch (err) { + expect(err, 'Bad error code').to.include({code: 5}); + } + }); +}); diff --git a/retail/interactive-tutorials/test/get-product.test.js b/retail/interactive-tutorials/test/get-product.test.js new file mode 100644 index 0000000000..7898314b6c --- /dev/null +++ b/retail/interactive-tutorials/test/get-product.test.js @@ -0,0 +1,70 @@ +// 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, after} = require('mocha'); +const {ProductServiceClient} = require('@google-cloud/retail'); +const {assert, expect} = require('chai'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); +const cwd = path.join(__dirname, '..'); + +describe('Get product', () => { + const retailClient = new ProductServiceClient(); + const productId = Math.random().toString(36).slice(2).toUpperCase(); + const projectNumber = process.env['GCLOUD_PROJECT']; + const name = `projects/${projectNumber}/locations/global/catalogs/default_catalog/branches/default_branch/products/${productId}`; + let stdout; + + before(async () => { + stdout = execSync( + `node interactive-tutorials/product/get-product.js ${productId}`, + {cwd} + ); + }); + + it('should check that product created', () => { + const regex = new RegExp(`Product ${productId} created`, 'g'); + assert.match(stdout, regex); + }); + + it('should check that get product started', () => { + assert.match(stdout, /Start product get operation/); + }); + + it('should check that get product finished', async () => { + const regex = new RegExp( + `Product ${productId} get operation finished`, + 'g' + ); + assert.match(stdout, regex); + }); + + it('should check that product deleted', async () => { + const regex = new RegExp(`Product ${productId} deleted`, 'g'); + assert.match(stdout, regex); + }); + + after(async () => { + try { + const product = await retailClient.getProduct({name: name}); + expect(product, 'The product not deleted').to.be.undefined; + } catch (err) { + expect(err, 'Bad error code').to.include({code: 5}); + } + }); +}); diff --git a/retail/interactive-tutorials/test/get-products-list.test.js b/retail/interactive-tutorials/test/get-products-list.test.js new file mode 100644 index 0000000000..d2a8350322 --- /dev/null +++ b/retail/interactive-tutorials/test/get-products-list.test.js @@ -0,0 +1,43 @@ +// 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('Get products list', () => { + let stdout; + + before(async () => { + stdout = execSync( + 'node interactive-tutorials/product/get-products-list.js', + {cwd} + ); + }); + + it('should check that get products list started', () => { + assert.match(stdout, /Start get products list/); + }); + + it('should check that get product list finished', async () => { + assert.match(stdout, /Get products list finished/); + }); +}); diff --git a/retail/interactive-tutorials/test/remove-fulfillment.test.js b/retail/interactive-tutorials/test/remove-fulfillment.test.js new file mode 100644 index 0000000000..b3d7773344 --- /dev/null +++ b/retail/interactive-tutorials/test/remove-fulfillment.test.js @@ -0,0 +1,98 @@ +// 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, after} = require('mocha'); +const {ProductServiceClient} = require('@google-cloud/retail'); +const {assert, expect} = require('chai'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); + +const cwd = path.join(__dirname, '..'); + +describe('Remove fulfillment', () => { + const retailClient = new ProductServiceClient(); + const productId = Math.random().toString(36).slice(2).toUpperCase(); + const projectNumber = process.env['GCLOUD_PROJECT']; + const name = `projects/${projectNumber}/locations/global/catalogs/default_catalog/branches/default_branch/products/${productId}`; + + let stdout; + + before(async () => { + stdout = execSync( + `node interactive-tutorials/product/remove-fulfillment-places.js ${productId}`, + {cwd} + ); + }); + + it('should check that product created', () => { + const regex = new RegExp(`Product ${productId} created`, 'g'); + assert.match(stdout, regex); + }); + + it('should check that remove fulfillment started', () => { + assert.match(stdout, /Start remove fulfillment/); + }); + + it('should check that add fulfillment finished', () => { + assert.match(stdout, /Remove fulfillment finished/); + }); + + const checkUpdatedProduct = updatedProduct => { + expect(updatedProduct).to.be.an('object'); + expect(updatedProduct.fulfillmentInfo).to.be.an('array'); + expect( + updatedProduct.fulfillmentInfo.length, + 'Fulfillment array is empty' + ).to.equal(1); + + const item = updatedProduct.fulfillmentInfo[0]; + expect(item).to.be.an('object'); + expect(item).to.have.all.keys('type', 'placeIds'); + expect(item.type).to.equal('same-day-delivery'); + expect(item.placeIds) + .to.be.an('array') + .that.includes('store3', 'store2') + .but.not.include('store1'); + }; + + it('should check that fulfillment removed correctly', async () => { + const regex = new RegExp('Updated product with current time: .*\\n', 'g'); + assert.match(stdout, regex); + const string = stdout + .match(regex) + .toString() + .replace('Updated product with current time: ', ''); + const updatedProduct = JSON.parse(string); + + checkUpdatedProduct(updatedProduct); + }); + + it('should check that product deleted', async () => { + const regex = new RegExp(`Product ${productId} deleted`, 'g'); + assert.match(stdout, regex); + }); + + after(async () => { + try { + const product = await retailClient.getProduct({name: name}); + expect(product, 'The product not deleted').to.be.undefined; + } catch (err) { + expect(err, 'Bad error code').to.include({code: 5}); + } + }); +}); diff --git a/retail/interactive-tutorials/test/set-inventory.test.js b/retail/interactive-tutorials/test/set-inventory.test.js new file mode 100644 index 0000000000..180051166b --- /dev/null +++ b/retail/interactive-tutorials/test/set-inventory.test.js @@ -0,0 +1,151 @@ +// 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, after} = require('mocha'); +const {ProductServiceClient} = require('@google-cloud/retail'); +const {assert, expect} = require('chai'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); + +const cwd = path.join(__dirname, '..'); + +describe('Set inventory', () => { + const retailClient = new ProductServiceClient(); + const productId = Math.random().toString(36).slice(2).toUpperCase(); + const projectNumber = process.env['GCLOUD_PROJECT']; + const name = `projects/${projectNumber}/locations/global/catalogs/default_catalog/branches/default_branch/products/${productId}`; + const product = { + priceInfo: { + price: 15.0, + originalPrice: 20.0, + cost: 8.0, + currencyCode: 'USD', + }, + fulfillmentInfo: [ + { + type: 'same-day-delivery', + placeIds: ['store3', 'store4'], + }, + ], + availableQuantity: { + value: 2, + }, + availability: 'IN_STOCK', + }; + let stdout; + + before(async () => { + stdout = execSync( + `node interactive-tutorials/product/set-inventory.js ${productId}`, + {cwd} + ); + }); + + it('should check that product created', () => { + const regex = new RegExp(`Product ${productId} created`, 'g'); + assert.match(stdout, regex); + }); + + it('should check that set inventory started', () => { + assert.match(stdout, /Start set inventory/); + }); + + it('should check that set inventory finished', () => { + assert.match(stdout, /Set inventory finished/); + }); + + const checkUpdatedProduct = updatedProduct => { + expect(updatedProduct).to.be.an('object'); + assert.containsAllDeepKeys(updatedProduct, product); + expect(updatedProduct.priceInfo.price, 'Price not equal').to.equal(15.0); + expect( + updatedProduct.priceInfo.originalPrice, + 'Original price not equal' + ).to.equal(20.0); + expect(updatedProduct.priceInfo.cost, 'Cost not equal').to.equal(8.0); + expect( + updatedProduct.priceInfo.currencyCode, + 'Currency code not equal' + ).to.equal('USD'); + expect(updatedProduct.fulfillmentInfo).to.be.an('array'); + expect( + updatedProduct.fulfillmentInfo.length, + 'Fulfillment array is empty' + ).to.equal(1); + + const fulfillmentItem = updatedProduct.fulfillmentInfo[0]; + expect(fulfillmentItem).to.be.an('object'); + expect(fulfillmentItem).to.have.all.keys('type', 'placeIds'); + expect(fulfillmentItem.type).to.equal('same-day-delivery'); + expect(fulfillmentItem.placeIds) + .to.be.an('array') + .that.includes('store3', 'store4'); + + expect( + updatedProduct.availableQuantity, + 'Available quantity not equal' + ).to.deep.equal({value: 2}); + expect(updatedProduct.availability, 'Availability not equal').to.equal( + 'IN_STOCK' + ); + }; + + it('should check that product updated correctly', async () => { + const regex = new RegExp( + `Updated product ${productId} with current time: .*\\n`, + 'g' + ); + assert.match(stdout, regex); + const string = stdout + .match(regex) + .toString() + .replace(`Updated product ${productId} with current time: `, ''); + const updatedProduct = JSON.parse(string); + + checkUpdatedProduct(updatedProduct); + }); + + it('should check that product has not been updated with outdated time', async () => { + const regex = new RegExp( + `Updated product ${productId} with outdated time: .*\\n`, + 'g' + ); + assert.match(stdout, regex); + const string = stdout + .match(regex) + .toString() + .replace(`Updated product ${productId} with outdated time: `, ''); + const updatedProduct = JSON.parse(string); + + checkUpdatedProduct(updatedProduct); + }); + + it('should check that product deleted', async () => { + const regex = new RegExp(`Product ${productId} deleted`, 'g'); + assert.match(stdout, regex); + }); + + after(async () => { + try { + const product = await retailClient.getProduct({name: name}); + expect(product, 'The product not deleted').to.be.undefined; + } catch (err) { + expect(err, 'Bad error code').to.include({code: 5}); + } + }); +}); diff --git a/retail/interactive-tutorials/test/update-product.test.js b/retail/interactive-tutorials/test/update-product.test.js new file mode 100644 index 0000000000..0f50ff290a --- /dev/null +++ b/retail/interactive-tutorials/test/update-product.test.js @@ -0,0 +1,105 @@ +// 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, after} = require('mocha'); +const {ProductServiceClient} = require('@google-cloud/retail'); +const {assert, expect} = require('chai'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); + +const cwd = path.join(__dirname, '..'); + +describe('Update product', () => { + const retailClient = new ProductServiceClient(); + const productId = Math.random().toString(36).slice(2).toUpperCase(); + const projectNumber = process.env['GCLOUD_PROJECT']; + const name = `projects/${projectNumber}/locations/global/catalogs/default_catalog/branches/default_branch/products/${productId}`; + const product = { + productId, + name, + title: 'Updated Nest Mini', + type: 'PRIMARY', + categories: ['Updated Speakers and displays'], + brands: ['Updated Google'], + priceInfo: { + price: 20.0, + originalPrice: 25.5, + currencyCode: 'EUR', + }, + availability: 'OUT_OF_STOCK', + }; + let stdout; + + before(async () => { + stdout = execSync( + `node interactive-tutorials/product/update-product.js ${productId}`, + {cwd} + ); + }); + + it('should check that product created', () => { + const regex = new RegExp(`Product ${productId} created`, 'g'); + assert.match(stdout, regex); + }); + + it('should check that product update started', () => { + assert.match(stdout, /Start product update/); + }); + + it('should check that product update finished', async () => { + const regex = new RegExp( + `Product ${productId} update finished: .*\\n`, + 'g' + ); + assert.match(stdout, regex); + const string = stdout + .match(regex) + .toString() + .replace(`Product ${productId} update finished: `, ''); + const updatedProduct = JSON.parse(string); + expect(updatedProduct).to.be.an('object'); + expect(updatedProduct).to.have.deep.property( + 'title', + product.title, + 'type', + product.type, + 'categories', + product.categories, + 'brands', + product.brands, + 'priceInfo', + product.priceInfo, + 'availability', + product.availability + ); + }); + + it('should check that product deleted', async () => { + const regex = new RegExp(`Product ${productId} deleted`, 'g'); + assert.match(stdout, regex); + }); + + after(async () => { + try { + const product = await retailClient.getProduct({name: name}); + expect(product, 'The product not deleted').to.be.undefined; + } catch (err) { + expect(err, 'Bad error code').to.include({code: 5}); + } + }); +});